<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>AJ</title>
    <meta name="generator" content="VuePress 1.5.0">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
    <script>
            var _hmt = _hmt || [];
            (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?51b8c2e72d1adf96524638ce85bb7d72";
            var s = document.getElementsByTagName("script")[0]; 
            s.parentNode.insertBefore(hm, s);

            // 引入谷歌,不需要可删除这段
            var hm1 = document.createElement("script");
            hm1.src = "https://www.googletagmanager.com/gtag/js?id=G-B7351EYS04";
            var s1 = document.getElementsByTagName("script")[0]; 
            s1.parentNode.insertBefore(hm1, s1);
            })();

            // 谷歌加载,不需要可删除
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());

            gtag('config', 'G-B7351EYS04');
        </script>
    <meta name="description" content="阿俊博客|记录一个程序员的成长历程 阿俊博客(blog.zhequtao.com)记录一个后端程序员的成长历程,分享他的学习笔记和心得,还有些开发必备技巧哦! java golang web html dev开发">
    <link rel="preload" href="/assets/css/0.styles.a3df589e.css" as="style"><link rel="preload" href="/assets/js/app.cb35c8f6.js" as="script"><link rel="preload" href="/assets/js/2.063846a6.js" as="script"><link rel="preload" href="/assets/js/4.1ffb4609.js" as="script"><link rel="preload" href="/assets/js/76.f54f3d4f.js" as="script"><link rel="prefetch" href="/assets/js/10.5629fe4d.js"><link rel="prefetch" href="/assets/js/100.8417ccea.js"><link rel="prefetch" href="/assets/js/101.37fdb377.js"><link rel="prefetch" href="/assets/js/102.848b686d.js"><link rel="prefetch" href="/assets/js/103.6a2489a0.js"><link rel="prefetch" href="/assets/js/104.99e8899f.js"><link rel="prefetch" href="/assets/js/105.8b741763.js"><link rel="prefetch" href="/assets/js/106.08163715.js"><link rel="prefetch" href="/assets/js/107.21801349.js"><link rel="prefetch" href="/assets/js/108.e3a2892b.js"><link rel="prefetch" href="/assets/js/109.dab5618c.js"><link rel="prefetch" href="/assets/js/11.cddc1623.js"><link rel="prefetch" href="/assets/js/110.f5249b39.js"><link rel="prefetch" href="/assets/js/111.9abf8bce.js"><link rel="prefetch" href="/assets/js/112.8eb86924.js"><link rel="prefetch" href="/assets/js/113.c180ed46.js"><link rel="prefetch" href="/assets/js/114.2370f5b5.js"><link rel="prefetch" href="/assets/js/115.88dc3fd8.js"><link rel="prefetch" href="/assets/js/116.63403600.js"><link rel="prefetch" href="/assets/js/117.83674aa0.js"><link rel="prefetch" href="/assets/js/118.9c58c685.js"><link rel="prefetch" href="/assets/js/119.621f9a70.js"><link rel="prefetch" href="/assets/js/12.ff3d03f5.js"><link rel="prefetch" href="/assets/js/120.a6d2b7f7.js"><link rel="prefetch" href="/assets/js/121.ae0ce9d1.js"><link rel="prefetch" href="/assets/js/122.de240e6d.js"><link rel="prefetch" href="/assets/js/123.b043e3e4.js"><link rel="prefetch" href="/assets/js/124.550af937.js"><link rel="prefetch" href="/assets/js/125.6f06b34c.js"><link rel="prefetch" href="/assets/js/126.38d64604.js"><link rel="prefetch" href="/assets/js/127.a948db56.js"><link rel="prefetch" href="/assets/js/128.4ca789e0.js"><link rel="prefetch" href="/assets/js/129.59be4505.js"><link rel="prefetch" href="/assets/js/13.e9f75cc3.js"><link rel="prefetch" href="/assets/js/130.ddae76a9.js"><link rel="prefetch" href="/assets/js/131.d969c265.js"><link rel="prefetch" href="/assets/js/132.5f43ce5c.js"><link rel="prefetch" href="/assets/js/133.b651af22.js"><link rel="prefetch" href="/assets/js/134.2499236a.js"><link rel="prefetch" href="/assets/js/135.4180596c.js"><link rel="prefetch" href="/assets/js/136.2c309233.js"><link rel="prefetch" href="/assets/js/137.72ca42dd.js"><link rel="prefetch" href="/assets/js/138.3772cd38.js"><link rel="prefetch" href="/assets/js/139.1d0a53da.js"><link rel="prefetch" href="/assets/js/14.be4b89ed.js"><link rel="prefetch" href="/assets/js/140.22368353.js"><link rel="prefetch" href="/assets/js/141.a14aef3c.js"><link rel="prefetch" href="/assets/js/142.2041ce3a.js"><link rel="prefetch" href="/assets/js/143.377262ec.js"><link rel="prefetch" href="/assets/js/144.8fcbc368.js"><link rel="prefetch" href="/assets/js/145.46da36bf.js"><link rel="prefetch" href="/assets/js/146.eceae0d9.js"><link rel="prefetch" href="/assets/js/147.e1bd6531.js"><link rel="prefetch" href="/assets/js/148.76f193ce.js"><link rel="prefetch" href="/assets/js/149.587bd581.js"><link rel="prefetch" href="/assets/js/15.e3219ac0.js"><link rel="prefetch" href="/assets/js/150.169c71e0.js"><link rel="prefetch" href="/assets/js/151.384021ea.js"><link rel="prefetch" href="/assets/js/152.0f20cf03.js"><link rel="prefetch" href="/assets/js/153.fd94af1e.js"><link rel="prefetch" href="/assets/js/154.a550f5dc.js"><link rel="prefetch" href="/assets/js/155.ba1ae86e.js"><link rel="prefetch" href="/assets/js/156.3b98ded0.js"><link rel="prefetch" href="/assets/js/157.cd378596.js"><link rel="prefetch" href="/assets/js/158.c138d0df.js"><link rel="prefetch" href="/assets/js/159.2635f7f4.js"><link rel="prefetch" href="/assets/js/16.c9c35d42.js"><link rel="prefetch" href="/assets/js/160.d51b4126.js"><link rel="prefetch" href="/assets/js/161.5dc29e7b.js"><link rel="prefetch" href="/assets/js/162.f257a92b.js"><link rel="prefetch" href="/assets/js/163.9eb75e40.js"><link rel="prefetch" href="/assets/js/164.8fb1e22b.js"><link rel="prefetch" href="/assets/js/165.49255503.js"><link rel="prefetch" href="/assets/js/166.e54539e6.js"><link rel="prefetch" href="/assets/js/167.a06acdb0.js"><link rel="prefetch" href="/assets/js/168.948ab620.js"><link rel="prefetch" href="/assets/js/169.7d756812.js"><link rel="prefetch" href="/assets/js/17.81067bc8.js"><link rel="prefetch" href="/assets/js/170.ffe63330.js"><link rel="prefetch" href="/assets/js/171.835398b9.js"><link rel="prefetch" href="/assets/js/172.3987be39.js"><link rel="prefetch" href="/assets/js/173.e3cedb8a.js"><link rel="prefetch" href="/assets/js/174.11a32588.js"><link rel="prefetch" href="/assets/js/175.da6f9782.js"><link rel="prefetch" href="/assets/js/176.50e55edc.js"><link rel="prefetch" href="/assets/js/177.a89a1d17.js"><link rel="prefetch" href="/assets/js/178.7ad3ce84.js"><link rel="prefetch" href="/assets/js/179.98a1343b.js"><link rel="prefetch" href="/assets/js/18.b67caf4c.js"><link rel="prefetch" href="/assets/js/180.4e98599b.js"><link rel="prefetch" href="/assets/js/181.dd885afd.js"><link rel="prefetch" href="/assets/js/182.789990c8.js"><link rel="prefetch" href="/assets/js/183.f11ca2fd.js"><link rel="prefetch" href="/assets/js/184.fcf128ec.js"><link rel="prefetch" href="/assets/js/185.54e1e9b6.js"><link rel="prefetch" href="/assets/js/186.db91021a.js"><link rel="prefetch" href="/assets/js/187.5309dd42.js"><link rel="prefetch" href="/assets/js/188.615821ea.js"><link rel="prefetch" href="/assets/js/189.f23f1d42.js"><link rel="prefetch" href="/assets/js/19.294a011c.js"><link rel="prefetch" href="/assets/js/190.efe894bc.js"><link rel="prefetch" href="/assets/js/191.0d14904a.js"><link rel="prefetch" href="/assets/js/192.efd25a9e.js"><link rel="prefetch" href="/assets/js/193.88151f34.js"><link rel="prefetch" href="/assets/js/194.efedce14.js"><link rel="prefetch" href="/assets/js/195.03ac15bb.js"><link rel="prefetch" href="/assets/js/196.fbc18389.js"><link rel="prefetch" href="/assets/js/197.0257ab5e.js"><link rel="prefetch" href="/assets/js/198.f1de2817.js"><link rel="prefetch" href="/assets/js/199.8f1c166b.js"><link rel="prefetch" href="/assets/js/20.1a41edb1.js"><link rel="prefetch" href="/assets/js/200.4af99727.js"><link rel="prefetch" href="/assets/js/201.9f8caef1.js"><link rel="prefetch" href="/assets/js/202.6f07d705.js"><link rel="prefetch" href="/assets/js/203.5012fe50.js"><link rel="prefetch" href="/assets/js/204.3a0dfd8e.js"><link rel="prefetch" href="/assets/js/205.0ba9b606.js"><link rel="prefetch" href="/assets/js/206.663a49ec.js"><link rel="prefetch" href="/assets/js/207.b2406149.js"><link rel="prefetch" href="/assets/js/208.b0b2dfd8.js"><link rel="prefetch" href="/assets/js/209.41a0ec9f.js"><link rel="prefetch" href="/assets/js/21.b6ea6f9a.js"><link rel="prefetch" href="/assets/js/210.6f36beb8.js"><link rel="prefetch" href="/assets/js/211.90ef6e5c.js"><link rel="prefetch" href="/assets/js/212.42339063.js"><link rel="prefetch" href="/assets/js/213.a2bfeda9.js"><link rel="prefetch" href="/assets/js/214.5c7eb42a.js"><link rel="prefetch" href="/assets/js/215.18260ae5.js"><link rel="prefetch" href="/assets/js/216.7678fd29.js"><link rel="prefetch" href="/assets/js/217.9d936f88.js"><link rel="prefetch" href="/assets/js/218.bac403c4.js"><link rel="prefetch" href="/assets/js/219.9d8cb16b.js"><link rel="prefetch" href="/assets/js/22.367cc253.js"><link rel="prefetch" href="/assets/js/220.375b7707.js"><link rel="prefetch" href="/assets/js/221.3e400da4.js"><link rel="prefetch" href="/assets/js/222.8fbd2857.js"><link rel="prefetch" href="/assets/js/223.76a10075.js"><link rel="prefetch" href="/assets/js/224.ff94cc4e.js"><link rel="prefetch" href="/assets/js/225.d4688ca6.js"><link rel="prefetch" href="/assets/js/226.b13b18af.js"><link rel="prefetch" href="/assets/js/227.288d0f96.js"><link rel="prefetch" href="/assets/js/228.60430ac0.js"><link rel="prefetch" href="/assets/js/229.da728342.js"><link rel="prefetch" href="/assets/js/23.bc3de730.js"><link rel="prefetch" href="/assets/js/230.d8417d20.js"><link rel="prefetch" href="/assets/js/231.6a9ce0b4.js"><link rel="prefetch" href="/assets/js/232.7611b413.js"><link rel="prefetch" href="/assets/js/233.94712cf9.js"><link rel="prefetch" href="/assets/js/234.93888298.js"><link rel="prefetch" href="/assets/js/235.62506981.js"><link rel="prefetch" href="/assets/js/236.5a055c7c.js"><link rel="prefetch" href="/assets/js/237.0a6c4902.js"><link rel="prefetch" href="/assets/js/238.e5f37663.js"><link rel="prefetch" href="/assets/js/239.331bba86.js"><link rel="prefetch" href="/assets/js/24.82f0901c.js"><link rel="prefetch" href="/assets/js/240.59591cfc.js"><link rel="prefetch" href="/assets/js/241.ce671f47.js"><link rel="prefetch" href="/assets/js/242.fb2542fa.js"><link rel="prefetch" href="/assets/js/243.74abc73d.js"><link rel="prefetch" href="/assets/js/244.ecd707b2.js"><link rel="prefetch" href="/assets/js/245.d728367b.js"><link rel="prefetch" href="/assets/js/246.9270e7fe.js"><link rel="prefetch" href="/assets/js/247.a421ba15.js"><link rel="prefetch" href="/assets/js/248.e759132e.js"><link rel="prefetch" href="/assets/js/249.3077fb46.js"><link rel="prefetch" href="/assets/js/25.95c551dc.js"><link rel="prefetch" href="/assets/js/250.5fe4dd03.js"><link rel="prefetch" href="/assets/js/251.4b8fe76c.js"><link rel="prefetch" href="/assets/js/252.0d1cf7ea.js"><link rel="prefetch" href="/assets/js/253.89d16ba0.js"><link rel="prefetch" href="/assets/js/254.8d1afc68.js"><link rel="prefetch" href="/assets/js/255.64e680cb.js"><link rel="prefetch" href="/assets/js/256.9defbd0e.js"><link rel="prefetch" href="/assets/js/257.1fef24fd.js"><link rel="prefetch" href="/assets/js/258.4e205286.js"><link rel="prefetch" href="/assets/js/259.f3d56efc.js"><link rel="prefetch" href="/assets/js/26.7fe56bac.js"><link rel="prefetch" href="/assets/js/260.378299e6.js"><link rel="prefetch" href="/assets/js/261.8e4fb397.js"><link rel="prefetch" href="/assets/js/262.54595d98.js"><link rel="prefetch" href="/assets/js/263.fb333dc1.js"><link rel="prefetch" href="/assets/js/264.13d13301.js"><link rel="prefetch" href="/assets/js/265.c85104bc.js"><link rel="prefetch" href="/assets/js/266.9f3d1f1c.js"><link rel="prefetch" href="/assets/js/267.fb392815.js"><link rel="prefetch" href="/assets/js/268.add7eacb.js"><link rel="prefetch" href="/assets/js/269.7e49fcc7.js"><link rel="prefetch" href="/assets/js/27.5547e5f0.js"><link rel="prefetch" href="/assets/js/270.22342070.js"><link rel="prefetch" href="/assets/js/271.59917b1a.js"><link rel="prefetch" href="/assets/js/272.4a4751d5.js"><link rel="prefetch" href="/assets/js/273.f4c2fa5c.js"><link rel="prefetch" href="/assets/js/274.1208bc94.js"><link rel="prefetch" href="/assets/js/275.f6528753.js"><link rel="prefetch" href="/assets/js/276.a68772cd.js"><link rel="prefetch" href="/assets/js/277.f154ab32.js"><link rel="prefetch" href="/assets/js/278.bb616a63.js"><link rel="prefetch" href="/assets/js/279.6a356cff.js"><link rel="prefetch" href="/assets/js/28.b08b2847.js"><link rel="prefetch" href="/assets/js/280.5afc20fc.js"><link rel="prefetch" href="/assets/js/281.3cd86225.js"><link rel="prefetch" href="/assets/js/282.3ecb92aa.js"><link rel="prefetch" href="/assets/js/283.85159ea7.js"><link rel="prefetch" href="/assets/js/284.b6545c68.js"><link rel="prefetch" href="/assets/js/285.5e83ee29.js"><link rel="prefetch" href="/assets/js/286.2aad298d.js"><link rel="prefetch" href="/assets/js/287.3ca76244.js"><link rel="prefetch" href="/assets/js/288.5b17963d.js"><link rel="prefetch" href="/assets/js/289.f47a759b.js"><link rel="prefetch" href="/assets/js/29.562dbf7d.js"><link rel="prefetch" href="/assets/js/290.36b603c7.js"><link rel="prefetch" href="/assets/js/291.a9bd8951.js"><link rel="prefetch" href="/assets/js/292.dfc54f28.js"><link rel="prefetch" href="/assets/js/293.2d061212.js"><link rel="prefetch" href="/assets/js/294.6d564a9e.js"><link rel="prefetch" href="/assets/js/295.a31dd593.js"><link rel="prefetch" href="/assets/js/296.3101e5e8.js"><link rel="prefetch" href="/assets/js/297.7efde936.js"><link rel="prefetch" href="/assets/js/298.8bb3aa68.js"><link rel="prefetch" href="/assets/js/299.8b51e6bd.js"><link rel="prefetch" href="/assets/js/3.76257eb7.js"><link rel="prefetch" href="/assets/js/30.221adea2.js"><link rel="prefetch" href="/assets/js/300.62effe45.js"><link rel="prefetch" href="/assets/js/301.98c863c5.js"><link rel="prefetch" href="/assets/js/302.e3493ab2.js"><link rel="prefetch" href="/assets/js/303.800c8028.js"><link rel="prefetch" href="/assets/js/304.b6f08986.js"><link rel="prefetch" href="/assets/js/305.09af356b.js"><link rel="prefetch" href="/assets/js/306.d0d3589d.js"><link rel="prefetch" href="/assets/js/307.ee2fd249.js"><link rel="prefetch" href="/assets/js/308.f3f76368.js"><link rel="prefetch" href="/assets/js/309.d2b5ce40.js"><link rel="prefetch" href="/assets/js/31.334fc8bb.js"><link rel="prefetch" href="/assets/js/310.b4fa2feb.js"><link rel="prefetch" href="/assets/js/311.7d747ef3.js"><link rel="prefetch" href="/assets/js/312.89bdff40.js"><link rel="prefetch" href="/assets/js/313.875b82fe.js"><link rel="prefetch" href="/assets/js/314.0bbe51c4.js"><link rel="prefetch" href="/assets/js/315.cc07dbcf.js"><link rel="prefetch" href="/assets/js/316.bc72b152.js"><link rel="prefetch" href="/assets/js/317.55462812.js"><link rel="prefetch" href="/assets/js/318.a158fda0.js"><link rel="prefetch" href="/assets/js/319.b03a5bd2.js"><link rel="prefetch" href="/assets/js/32.d6826b16.js"><link rel="prefetch" href="/assets/js/320.a5bd19b0.js"><link rel="prefetch" href="/assets/js/321.4f9faaa7.js"><link rel="prefetch" href="/assets/js/322.dbd3b4fa.js"><link rel="prefetch" href="/assets/js/323.a04e2062.js"><link rel="prefetch" href="/assets/js/324.c45b46cf.js"><link rel="prefetch" href="/assets/js/325.cd1460c4.js"><link rel="prefetch" href="/assets/js/326.bd90ef85.js"><link rel="prefetch" href="/assets/js/327.8bf38ef7.js"><link rel="prefetch" href="/assets/js/328.99e9aed3.js"><link rel="prefetch" href="/assets/js/329.de0012cb.js"><link rel="prefetch" href="/assets/js/33.b1059062.js"><link rel="prefetch" href="/assets/js/330.59f11391.js"><link rel="prefetch" href="/assets/js/331.6d16a13c.js"><link rel="prefetch" href="/assets/js/332.922ca235.js"><link rel="prefetch" href="/assets/js/333.c94c3602.js"><link rel="prefetch" href="/assets/js/334.77e02010.js"><link rel="prefetch" href="/assets/js/335.1e0c4f7b.js"><link rel="prefetch" href="/assets/js/336.5675dc4f.js"><link rel="prefetch" href="/assets/js/337.bb6e11dc.js"><link rel="prefetch" href="/assets/js/338.294981e9.js"><link rel="prefetch" href="/assets/js/339.d0376372.js"><link rel="prefetch" href="/assets/js/34.0c7d5782.js"><link rel="prefetch" href="/assets/js/340.64596428.js"><link rel="prefetch" href="/assets/js/341.ec0f9409.js"><link rel="prefetch" href="/assets/js/342.7abc47c4.js"><link rel="prefetch" href="/assets/js/343.4262d486.js"><link rel="prefetch" href="/assets/js/344.8729ad8c.js"><link rel="prefetch" href="/assets/js/345.c210d888.js"><link rel="prefetch" href="/assets/js/346.6f42f7cb.js"><link rel="prefetch" href="/assets/js/347.81b41ae5.js"><link rel="prefetch" href="/assets/js/348.07eca37c.js"><link rel="prefetch" href="/assets/js/349.8019d6f3.js"><link rel="prefetch" href="/assets/js/35.ae14e37f.js"><link rel="prefetch" href="/assets/js/350.57da2e7b.js"><link rel="prefetch" href="/assets/js/351.2e99afdf.js"><link rel="prefetch" href="/assets/js/352.67dd88b7.js"><link rel="prefetch" href="/assets/js/353.15b9f624.js"><link rel="prefetch" href="/assets/js/354.a63e8432.js"><link rel="prefetch" href="/assets/js/355.bbc16ee9.js"><link rel="prefetch" href="/assets/js/356.ff63d3bb.js"><link rel="prefetch" href="/assets/js/357.4fb2d941.js"><link rel="prefetch" href="/assets/js/358.55182977.js"><link rel="prefetch" href="/assets/js/359.265c3d26.js"><link rel="prefetch" href="/assets/js/36.b9ed4cf1.js"><link rel="prefetch" href="/assets/js/360.ced80eb3.js"><link rel="prefetch" href="/assets/js/361.afe6ba84.js"><link rel="prefetch" href="/assets/js/362.c2b62518.js"><link rel="prefetch" href="/assets/js/363.0c4a4800.js"><link rel="prefetch" href="/assets/js/364.ce60291b.js"><link rel="prefetch" href="/assets/js/365.0e3a61f9.js"><link rel="prefetch" href="/assets/js/366.d53ccb03.js"><link rel="prefetch" href="/assets/js/367.689e464d.js"><link rel="prefetch" href="/assets/js/368.418c571f.js"><link rel="prefetch" href="/assets/js/369.c2fff3c8.js"><link rel="prefetch" href="/assets/js/37.a021ac57.js"><link rel="prefetch" href="/assets/js/370.a932b958.js"><link rel="prefetch" href="/assets/js/371.7d153241.js"><link rel="prefetch" href="/assets/js/372.fb9878fa.js"><link rel="prefetch" href="/assets/js/373.85772e03.js"><link rel="prefetch" href="/assets/js/374.b4a8b1b6.js"><link rel="prefetch" href="/assets/js/375.32f70596.js"><link rel="prefetch" href="/assets/js/376.a16d79a8.js"><link rel="prefetch" href="/assets/js/377.c996b7e1.js"><link rel="prefetch" href="/assets/js/378.d37d15c7.js"><link rel="prefetch" href="/assets/js/379.b81ba7dd.js"><link rel="prefetch" href="/assets/js/38.89138658.js"><link rel="prefetch" href="/assets/js/380.524c9b31.js"><link rel="prefetch" href="/assets/js/381.7ebfd6db.js"><link rel="prefetch" href="/assets/js/382.29edda0f.js"><link rel="prefetch" href="/assets/js/383.9642a212.js"><link rel="prefetch" href="/assets/js/384.086e3b42.js"><link rel="prefetch" href="/assets/js/385.a9bb46a8.js"><link rel="prefetch" href="/assets/js/386.f2561a39.js"><link rel="prefetch" href="/assets/js/387.ba9b6aaa.js"><link rel="prefetch" href="/assets/js/388.e0ace495.js"><link rel="prefetch" href="/assets/js/389.ba8c09dd.js"><link rel="prefetch" href="/assets/js/39.04f331e3.js"><link rel="prefetch" href="/assets/js/390.de1bb48b.js"><link rel="prefetch" href="/assets/js/391.7cc6edeb.js"><link rel="prefetch" href="/assets/js/392.0493a6f7.js"><link rel="prefetch" href="/assets/js/393.ba2d3e62.js"><link rel="prefetch" href="/assets/js/394.b3aa9224.js"><link rel="prefetch" href="/assets/js/395.f4df3a60.js"><link rel="prefetch" href="/assets/js/396.09644790.js"><link rel="prefetch" href="/assets/js/397.76163964.js"><link rel="prefetch" href="/assets/js/398.377fd8fc.js"><link rel="prefetch" href="/assets/js/399.39059be5.js"><link rel="prefetch" href="/assets/js/40.a21abf05.js"><link rel="prefetch" href="/assets/js/400.559a547f.js"><link rel="prefetch" href="/assets/js/401.bc6d738c.js"><link rel="prefetch" href="/assets/js/402.c504ed7b.js"><link rel="prefetch" href="/assets/js/403.77a0af9c.js"><link rel="prefetch" href="/assets/js/404.0f408cc6.js"><link rel="prefetch" href="/assets/js/405.90b0bab6.js"><link rel="prefetch" href="/assets/js/406.01b11432.js"><link rel="prefetch" href="/assets/js/407.58991ce5.js"><link rel="prefetch" href="/assets/js/408.9806278e.js"><link rel="prefetch" href="/assets/js/409.8d9b4bb3.js"><link rel="prefetch" href="/assets/js/41.6bcfc592.js"><link rel="prefetch" href="/assets/js/410.02dee620.js"><link rel="prefetch" href="/assets/js/411.3d12d3a6.js"><link rel="prefetch" href="/assets/js/412.37a62624.js"><link rel="prefetch" href="/assets/js/413.bda7ca34.js"><link rel="prefetch" href="/assets/js/414.2abb6547.js"><link rel="prefetch" href="/assets/js/415.1d271923.js"><link rel="prefetch" href="/assets/js/416.d1b11dfe.js"><link rel="prefetch" href="/assets/js/417.fcbf07ff.js"><link rel="prefetch" href="/assets/js/418.524d40ba.js"><link rel="prefetch" href="/assets/js/419.f264e463.js"><link rel="prefetch" href="/assets/js/42.ec85a270.js"><link rel="prefetch" href="/assets/js/420.8b99e60d.js"><link rel="prefetch" href="/assets/js/421.c697d876.js"><link rel="prefetch" href="/assets/js/422.4af54ae0.js"><link rel="prefetch" href="/assets/js/423.b75f24ff.js"><link rel="prefetch" href="/assets/js/424.ea80054f.js"><link rel="prefetch" href="/assets/js/425.804b48b0.js"><link rel="prefetch" href="/assets/js/426.ffed8383.js"><link rel="prefetch" href="/assets/js/427.2040bd22.js"><link rel="prefetch" href="/assets/js/428.b878fb56.js"><link rel="prefetch" href="/assets/js/429.f81fd922.js"><link rel="prefetch" href="/assets/js/43.c174449d.js"><link rel="prefetch" href="/assets/js/430.16f328ab.js"><link rel="prefetch" href="/assets/js/431.56f11924.js"><link rel="prefetch" href="/assets/js/432.e4c77710.js"><link rel="prefetch" href="/assets/js/433.29acf14b.js"><link rel="prefetch" href="/assets/js/434.33ee22fc.js"><link rel="prefetch" href="/assets/js/435.516f7600.js"><link rel="prefetch" href="/assets/js/436.28ae526a.js"><link rel="prefetch" href="/assets/js/437.b9bac473.js"><link rel="prefetch" href="/assets/js/438.711bd934.js"><link rel="prefetch" href="/assets/js/439.fe5f28bd.js"><link rel="prefetch" href="/assets/js/44.8704338b.js"><link rel="prefetch" href="/assets/js/440.b2f48747.js"><link rel="prefetch" href="/assets/js/441.4862a724.js"><link rel="prefetch" href="/assets/js/442.751f8ae7.js"><link rel="prefetch" href="/assets/js/443.9998dbe9.js"><link rel="prefetch" href="/assets/js/444.23d3f688.js"><link rel="prefetch" href="/assets/js/445.72419f35.js"><link rel="prefetch" href="/assets/js/446.21e02b7b.js"><link rel="prefetch" href="/assets/js/447.6bd039e5.js"><link rel="prefetch" href="/assets/js/448.af29ff31.js"><link rel="prefetch" href="/assets/js/449.bbdca196.js"><link rel="prefetch" href="/assets/js/45.f8a2a3b3.js"><link rel="prefetch" href="/assets/js/450.32e470b8.js"><link rel="prefetch" href="/assets/js/451.f4c8ff6a.js"><link rel="prefetch" href="/assets/js/452.c0ec8943.js"><link rel="prefetch" href="/assets/js/453.5af475c6.js"><link rel="prefetch" href="/assets/js/454.567aa6c1.js"><link rel="prefetch" href="/assets/js/455.326072d1.js"><link rel="prefetch" href="/assets/js/456.64b88847.js"><link rel="prefetch" href="/assets/js/457.61c91559.js"><link rel="prefetch" href="/assets/js/458.4f4d43d6.js"><link rel="prefetch" href="/assets/js/459.a88891cb.js"><link rel="prefetch" href="/assets/js/46.90855a0f.js"><link rel="prefetch" href="/assets/js/460.fb9e15f6.js"><link rel="prefetch" href="/assets/js/461.998a4991.js"><link rel="prefetch" href="/assets/js/462.56ecfb03.js"><link rel="prefetch" href="/assets/js/463.582cd053.js"><link rel="prefetch" href="/assets/js/464.f12a0050.js"><link rel="prefetch" href="/assets/js/465.cc3b08a8.js"><link rel="prefetch" href="/assets/js/466.ea7e4ce2.js"><link rel="prefetch" href="/assets/js/467.58700d93.js"><link rel="prefetch" href="/assets/js/468.bb9998cd.js"><link rel="prefetch" href="/assets/js/469.232d261d.js"><link rel="prefetch" href="/assets/js/47.02516d33.js"><link rel="prefetch" href="/assets/js/470.90ab2be8.js"><link rel="prefetch" href="/assets/js/471.3652fec6.js"><link rel="prefetch" href="/assets/js/472.bc7517c9.js"><link rel="prefetch" href="/assets/js/473.27b7892f.js"><link rel="prefetch" href="/assets/js/474.0d488768.js"><link rel="prefetch" href="/assets/js/475.bc33cf17.js"><link rel="prefetch" href="/assets/js/476.76ce67eb.js"><link rel="prefetch" href="/assets/js/477.a20657f6.js"><link rel="prefetch" href="/assets/js/478.8905ef26.js"><link rel="prefetch" href="/assets/js/479.23ec3dc9.js"><link rel="prefetch" href="/assets/js/48.8d38983c.js"><link rel="prefetch" href="/assets/js/480.105bf58e.js"><link rel="prefetch" href="/assets/js/481.d62a3699.js"><link rel="prefetch" href="/assets/js/482.6cb10cdb.js"><link rel="prefetch" href="/assets/js/483.15b9ef53.js"><link rel="prefetch" href="/assets/js/484.794aff9c.js"><link rel="prefetch" href="/assets/js/485.3e6ef3cb.js"><link rel="prefetch" href="/assets/js/486.fc20eb22.js"><link rel="prefetch" href="/assets/js/487.2a4f7d47.js"><link rel="prefetch" href="/assets/js/488.24ba9af5.js"><link rel="prefetch" href="/assets/js/489.d451928e.js"><link rel="prefetch" href="/assets/js/49.bd70c59c.js"><link rel="prefetch" href="/assets/js/490.d83e4fc7.js"><link rel="prefetch" href="/assets/js/491.0210a738.js"><link rel="prefetch" href="/assets/js/492.3a69cd85.js"><link rel="prefetch" href="/assets/js/493.89d2920f.js"><link rel="prefetch" href="/assets/js/494.b7d1c15e.js"><link rel="prefetch" href="/assets/js/495.7ccfe17f.js"><link rel="prefetch" href="/assets/js/496.0d6c912a.js"><link rel="prefetch" href="/assets/js/497.087ca2c6.js"><link rel="prefetch" href="/assets/js/498.f2b3c894.js"><link rel="prefetch" href="/assets/js/499.e741f312.js"><link rel="prefetch" href="/assets/js/5.405f2620.js"><link rel="prefetch" href="/assets/js/50.9df07553.js"><link rel="prefetch" href="/assets/js/500.cb9babb9.js"><link rel="prefetch" href="/assets/js/501.63a859b6.js"><link rel="prefetch" href="/assets/js/502.f346b273.js"><link rel="prefetch" href="/assets/js/503.cdcd3de3.js"><link rel="prefetch" href="/assets/js/504.e83ec450.js"><link rel="prefetch" href="/assets/js/505.95f18293.js"><link rel="prefetch" href="/assets/js/506.02060a3c.js"><link rel="prefetch" href="/assets/js/507.859d6ae4.js"><link rel="prefetch" href="/assets/js/508.9724d886.js"><link rel="prefetch" href="/assets/js/509.e17dd53e.js"><link rel="prefetch" href="/assets/js/51.3dfc6350.js"><link rel="prefetch" href="/assets/js/510.ea0c942f.js"><link rel="prefetch" href="/assets/js/511.64a7f9a8.js"><link rel="prefetch" href="/assets/js/512.6cce418a.js"><link rel="prefetch" href="/assets/js/513.ea813fe8.js"><link rel="prefetch" href="/assets/js/514.10242470.js"><link rel="prefetch" href="/assets/js/515.5308bdf6.js"><link rel="prefetch" href="/assets/js/516.dfb113bc.js"><link rel="prefetch" href="/assets/js/517.96c71069.js"><link rel="prefetch" href="/assets/js/518.5594480e.js"><link rel="prefetch" href="/assets/js/519.91e848ae.js"><link rel="prefetch" href="/assets/js/52.dd230cd7.js"><link rel="prefetch" href="/assets/js/520.ebe69ce9.js"><link rel="prefetch" href="/assets/js/521.92b80342.js"><link rel="prefetch" href="/assets/js/522.6ce581ea.js"><link rel="prefetch" href="/assets/js/523.40b7f2f9.js"><link rel="prefetch" href="/assets/js/524.4ef256d3.js"><link rel="prefetch" href="/assets/js/525.19741e4a.js"><link rel="prefetch" href="/assets/js/526.e5de1675.js"><link rel="prefetch" href="/assets/js/527.9a79cd42.js"><link rel="prefetch" href="/assets/js/528.72732eb8.js"><link rel="prefetch" href="/assets/js/529.2ea03e45.js"><link rel="prefetch" href="/assets/js/53.a349c565.js"><link rel="prefetch" href="/assets/js/530.5d1103e7.js"><link rel="prefetch" href="/assets/js/531.82b032d6.js"><link rel="prefetch" href="/assets/js/532.12ee4beb.js"><link rel="prefetch" href="/assets/js/533.db9a90f7.js"><link rel="prefetch" href="/assets/js/534.fe139db4.js"><link rel="prefetch" href="/assets/js/535.056a6fbb.js"><link rel="prefetch" href="/assets/js/536.6bf85c15.js"><link rel="prefetch" href="/assets/js/537.6e2e1ccf.js"><link rel="prefetch" href="/assets/js/538.54eddb3b.js"><link rel="prefetch" href="/assets/js/539.6f00a207.js"><link rel="prefetch" href="/assets/js/54.e292b52f.js"><link rel="prefetch" href="/assets/js/540.9c956205.js"><link rel="prefetch" href="/assets/js/541.50f41228.js"><link rel="prefetch" href="/assets/js/542.a2b1879e.js"><link rel="prefetch" href="/assets/js/543.4e5e17c9.js"><link rel="prefetch" href="/assets/js/544.63d85227.js"><link rel="prefetch" href="/assets/js/545.c3923644.js"><link rel="prefetch" href="/assets/js/546.e64ad073.js"><link rel="prefetch" href="/assets/js/547.35a8752d.js"><link rel="prefetch" href="/assets/js/548.b62a1348.js"><link rel="prefetch" href="/assets/js/549.369e2ea0.js"><link rel="prefetch" href="/assets/js/55.21bb2983.js"><link rel="prefetch" href="/assets/js/550.b4632248.js"><link rel="prefetch" href="/assets/js/551.18f1879c.js"><link rel="prefetch" href="/assets/js/552.162e63cd.js"><link rel="prefetch" href="/assets/js/553.6998130e.js"><link rel="prefetch" href="/assets/js/554.89126c3d.js"><link rel="prefetch" href="/assets/js/555.a5f63b8a.js"><link rel="prefetch" href="/assets/js/556.35381cef.js"><link rel="prefetch" href="/assets/js/557.ceeecf52.js"><link rel="prefetch" href="/assets/js/558.253e6e4f.js"><link rel="prefetch" href="/assets/js/559.5cfbb773.js"><link rel="prefetch" href="/assets/js/56.5382d6b4.js"><link rel="prefetch" href="/assets/js/560.cca52f22.js"><link rel="prefetch" href="/assets/js/561.ea8d1141.js"><link rel="prefetch" href="/assets/js/562.c32e7b96.js"><link rel="prefetch" href="/assets/js/563.9bdd42e7.js"><link rel="prefetch" href="/assets/js/564.b3b87ec0.js"><link rel="prefetch" href="/assets/js/565.4be0d0f7.js"><link rel="prefetch" href="/assets/js/566.9f379d12.js"><link rel="prefetch" href="/assets/js/567.261e3181.js"><link rel="prefetch" href="/assets/js/568.4229e365.js"><link rel="prefetch" href="/assets/js/569.e662c167.js"><link rel="prefetch" href="/assets/js/57.8129f7e0.js"><link rel="prefetch" href="/assets/js/570.97ff6423.js"><link rel="prefetch" href="/assets/js/571.de1377cd.js"><link rel="prefetch" href="/assets/js/572.48b8400b.js"><link rel="prefetch" href="/assets/js/573.8251ebaf.js"><link rel="prefetch" href="/assets/js/574.ec3d6c1e.js"><link rel="prefetch" href="/assets/js/575.b0d429a1.js"><link rel="prefetch" href="/assets/js/576.98ce9170.js"><link rel="prefetch" href="/assets/js/577.85fc2017.js"><link rel="prefetch" href="/assets/js/578.1393ac7f.js"><link rel="prefetch" href="/assets/js/579.1340e178.js"><link rel="prefetch" href="/assets/js/58.85ac2740.js"><link rel="prefetch" href="/assets/js/580.a5979445.js"><link rel="prefetch" href="/assets/js/581.effdc269.js"><link rel="prefetch" href="/assets/js/582.13276063.js"><link rel="prefetch" href="/assets/js/583.357a2443.js"><link rel="prefetch" href="/assets/js/584.338ef731.js"><link rel="prefetch" href="/assets/js/585.87932741.js"><link rel="prefetch" href="/assets/js/586.b1d6e000.js"><link rel="prefetch" href="/assets/js/587.ed5b8377.js"><link rel="prefetch" href="/assets/js/588.16d2c418.js"><link rel="prefetch" href="/assets/js/589.c96fd7fa.js"><link rel="prefetch" href="/assets/js/59.0b225757.js"><link rel="prefetch" href="/assets/js/590.1a06b2a0.js"><link rel="prefetch" href="/assets/js/591.0efd886c.js"><link rel="prefetch" href="/assets/js/592.b22d0ef5.js"><link rel="prefetch" href="/assets/js/593.84ed6ebe.js"><link rel="prefetch" href="/assets/js/594.cd721b88.js"><link rel="prefetch" href="/assets/js/595.2400817a.js"><link rel="prefetch" href="/assets/js/596.f2c512d1.js"><link rel="prefetch" href="/assets/js/597.df10ec57.js"><link rel="prefetch" href="/assets/js/598.61ef6a7d.js"><link rel="prefetch" href="/assets/js/599.0bebb562.js"><link rel="prefetch" href="/assets/js/6.29d112b1.js"><link rel="prefetch" href="/assets/js/60.3bbab51d.js"><link rel="prefetch" href="/assets/js/600.1ea7596f.js"><link rel="prefetch" href="/assets/js/601.f2642bb3.js"><link rel="prefetch" href="/assets/js/602.400cc987.js"><link rel="prefetch" href="/assets/js/603.db77d173.js"><link rel="prefetch" href="/assets/js/604.0ffa30ae.js"><link rel="prefetch" href="/assets/js/605.32ca9607.js"><link rel="prefetch" href="/assets/js/606.8c1e5683.js"><link rel="prefetch" href="/assets/js/607.9c9463ef.js"><link rel="prefetch" href="/assets/js/608.d5efa77e.js"><link rel="prefetch" href="/assets/js/609.5bbffb7d.js"><link rel="prefetch" href="/assets/js/61.f7301486.js"><link rel="prefetch" href="/assets/js/610.5b0fc9da.js"><link rel="prefetch" href="/assets/js/611.bb8058c9.js"><link rel="prefetch" href="/assets/js/612.b0788f43.js"><link rel="prefetch" href="/assets/js/613.49511e65.js"><link rel="prefetch" href="/assets/js/614.fae3eacf.js"><link rel="prefetch" href="/assets/js/615.359e5899.js"><link rel="prefetch" href="/assets/js/616.905132f4.js"><link rel="prefetch" href="/assets/js/617.6c8c594e.js"><link rel="prefetch" href="/assets/js/618.6ac4f3ff.js"><link rel="prefetch" href="/assets/js/619.411a0c14.js"><link rel="prefetch" href="/assets/js/62.9aeede84.js"><link rel="prefetch" href="/assets/js/620.56155724.js"><link rel="prefetch" href="/assets/js/621.149d7933.js"><link rel="prefetch" href="/assets/js/622.f0c9bc08.js"><link rel="prefetch" href="/assets/js/623.e0989fbe.js"><link rel="prefetch" href="/assets/js/624.80b1f6a9.js"><link rel="prefetch" href="/assets/js/625.a0a392c4.js"><link rel="prefetch" href="/assets/js/626.56fd4e8a.js"><link rel="prefetch" href="/assets/js/627.264e7313.js"><link rel="prefetch" href="/assets/js/628.7a868b19.js"><link rel="prefetch" href="/assets/js/629.e7e15da1.js"><link rel="prefetch" href="/assets/js/63.4df55c8b.js"><link rel="prefetch" href="/assets/js/630.998c9b61.js"><link rel="prefetch" href="/assets/js/631.69aa049c.js"><link rel="prefetch" href="/assets/js/632.da3882c1.js"><link rel="prefetch" href="/assets/js/633.0d49adf0.js"><link rel="prefetch" href="/assets/js/634.f9984ede.js"><link rel="prefetch" href="/assets/js/635.f0439f65.js"><link rel="prefetch" href="/assets/js/636.54de4194.js"><link rel="prefetch" href="/assets/js/637.55d1c226.js"><link rel="prefetch" href="/assets/js/638.2a9a510f.js"><link rel="prefetch" href="/assets/js/639.8bec360e.js"><link rel="prefetch" href="/assets/js/64.7f3e5e81.js"><link rel="prefetch" href="/assets/js/640.30d7f96e.js"><link rel="prefetch" href="/assets/js/641.68100098.js"><link rel="prefetch" href="/assets/js/642.4b793817.js"><link rel="prefetch" href="/assets/js/643.d86a81ea.js"><link rel="prefetch" href="/assets/js/644.76327ea2.js"><link rel="prefetch" href="/assets/js/645.0ac6a923.js"><link rel="prefetch" href="/assets/js/646.cd92f728.js"><link rel="prefetch" href="/assets/js/647.f2c624e1.js"><link rel="prefetch" href="/assets/js/648.c8f3b955.js"><link rel="prefetch" href="/assets/js/649.6370753b.js"><link rel="prefetch" href="/assets/js/65.2beeae9b.js"><link rel="prefetch" href="/assets/js/650.afe31909.js"><link rel="prefetch" href="/assets/js/651.87971ec0.js"><link rel="prefetch" href="/assets/js/652.0adf10a6.js"><link rel="prefetch" href="/assets/js/653.1f655726.js"><link rel="prefetch" href="/assets/js/654.53e24c7c.js"><link rel="prefetch" href="/assets/js/655.c95a66ea.js"><link rel="prefetch" href="/assets/js/656.38b5a5ea.js"><link rel="prefetch" href="/assets/js/657.3167aa94.js"><link rel="prefetch" href="/assets/js/658.7c40ff62.js"><link rel="prefetch" href="/assets/js/659.5d2b9b54.js"><link rel="prefetch" href="/assets/js/66.44b214db.js"><link rel="prefetch" href="/assets/js/660.96a8da9e.js"><link rel="prefetch" href="/assets/js/661.4de3b6c1.js"><link rel="prefetch" href="/assets/js/662.7d9bf181.js"><link rel="prefetch" href="/assets/js/663.4ccaf40a.js"><link rel="prefetch" href="/assets/js/664.7ab4fa53.js"><link rel="prefetch" href="/assets/js/665.32245d26.js"><link rel="prefetch" href="/assets/js/666.e6617151.js"><link rel="prefetch" href="/assets/js/667.fb3b0547.js"><link rel="prefetch" href="/assets/js/668.3d1b2e36.js"><link rel="prefetch" href="/assets/js/669.b769905f.js"><link rel="prefetch" href="/assets/js/67.c31aaacf.js"><link rel="prefetch" href="/assets/js/670.88ed3af3.js"><link rel="prefetch" href="/assets/js/671.1aff6bfe.js"><link rel="prefetch" href="/assets/js/672.c90888f7.js"><link rel="prefetch" href="/assets/js/673.81241fdc.js"><link rel="prefetch" href="/assets/js/674.838a424d.js"><link rel="prefetch" href="/assets/js/675.603ac896.js"><link rel="prefetch" href="/assets/js/676.ff44b5dc.js"><link rel="prefetch" href="/assets/js/677.41a8087a.js"><link rel="prefetch" href="/assets/js/678.f0eb8d04.js"><link rel="prefetch" href="/assets/js/679.db78199e.js"><link rel="prefetch" href="/assets/js/68.08607c89.js"><link rel="prefetch" href="/assets/js/680.8fded9d4.js"><link rel="prefetch" href="/assets/js/681.0b019dfd.js"><link rel="prefetch" href="/assets/js/682.746e9190.js"><link rel="prefetch" href="/assets/js/683.d5c00845.js"><link rel="prefetch" href="/assets/js/684.b3207cad.js"><link rel="prefetch" href="/assets/js/685.d78f18ba.js"><link rel="prefetch" href="/assets/js/686.5aaecd19.js"><link rel="prefetch" href="/assets/js/687.821a06f4.js"><link rel="prefetch" href="/assets/js/688.8bbc1890.js"><link rel="prefetch" href="/assets/js/689.79b49e8c.js"><link rel="prefetch" href="/assets/js/69.509245d6.js"><link rel="prefetch" href="/assets/js/690.fa62f9dd.js"><link rel="prefetch" href="/assets/js/691.d3eb1a60.js"><link rel="prefetch" href="/assets/js/692.738f14bb.js"><link rel="prefetch" href="/assets/js/693.e6a497a2.js"><link rel="prefetch" href="/assets/js/694.6eea1c54.js"><link rel="prefetch" href="/assets/js/695.88e6acee.js"><link rel="prefetch" href="/assets/js/696.de10297f.js"><link rel="prefetch" href="/assets/js/697.96d04062.js"><link rel="prefetch" href="/assets/js/698.200cc84f.js"><link rel="prefetch" href="/assets/js/699.f11fc627.js"><link rel="prefetch" href="/assets/js/7.c16198b8.js"><link rel="prefetch" href="/assets/js/70.5f6285b1.js"><link rel="prefetch" href="/assets/js/700.93d48f59.js"><link rel="prefetch" href="/assets/js/701.b861f29a.js"><link rel="prefetch" href="/assets/js/702.dc82e05c.js"><link rel="prefetch" href="/assets/js/703.625ce87c.js"><link rel="prefetch" href="/assets/js/704.005a0a7c.js"><link rel="prefetch" href="/assets/js/705.16ad9230.js"><link rel="prefetch" href="/assets/js/706.4eead30a.js"><link rel="prefetch" href="/assets/js/707.730306ce.js"><link rel="prefetch" href="/assets/js/708.e37e743a.js"><link rel="prefetch" href="/assets/js/709.f2144f52.js"><link rel="prefetch" href="/assets/js/71.d5d0dae5.js"><link rel="prefetch" href="/assets/js/710.ee9d9b17.js"><link rel="prefetch" href="/assets/js/711.2813c338.js"><link rel="prefetch" href="/assets/js/712.e801bce4.js"><link rel="prefetch" href="/assets/js/713.21fc267c.js"><link rel="prefetch" href="/assets/js/714.4ec35525.js"><link rel="prefetch" href="/assets/js/715.fdc3cc84.js"><link rel="prefetch" href="/assets/js/716.324932ad.js"><link rel="prefetch" href="/assets/js/717.a072a66f.js"><link rel="prefetch" href="/assets/js/718.575e0305.js"><link rel="prefetch" href="/assets/js/719.5fdd55de.js"><link rel="prefetch" href="/assets/js/72.25648231.js"><link rel="prefetch" href="/assets/js/720.61477f23.js"><link rel="prefetch" href="/assets/js/721.c8bdab00.js"><link rel="prefetch" href="/assets/js/722.9255f385.js"><link rel="prefetch" href="/assets/js/723.f27792a4.js"><link rel="prefetch" href="/assets/js/724.cd504f88.js"><link rel="prefetch" href="/assets/js/725.55c845fa.js"><link rel="prefetch" href="/assets/js/726.bb49a9db.js"><link rel="prefetch" href="/assets/js/727.53d587fe.js"><link rel="prefetch" href="/assets/js/728.86972387.js"><link rel="prefetch" href="/assets/js/729.02fa0263.js"><link rel="prefetch" href="/assets/js/73.29902c1f.js"><link rel="prefetch" href="/assets/js/730.817156d1.js"><link rel="prefetch" href="/assets/js/731.6f5d6735.js"><link rel="prefetch" href="/assets/js/732.9a5ff781.js"><link rel="prefetch" href="/assets/js/733.bcb13916.js"><link rel="prefetch" href="/assets/js/734.11482b19.js"><link rel="prefetch" href="/assets/js/735.8c0d62f3.js"><link rel="prefetch" href="/assets/js/736.06465705.js"><link rel="prefetch" href="/assets/js/737.79741d87.js"><link rel="prefetch" href="/assets/js/738.cad12ff9.js"><link rel="prefetch" href="/assets/js/739.cb09e552.js"><link rel="prefetch" href="/assets/js/74.bcf666a0.js"><link rel="prefetch" href="/assets/js/740.029b1950.js"><link rel="prefetch" href="/assets/js/741.b937216a.js"><link rel="prefetch" href="/assets/js/742.ec02c706.js"><link rel="prefetch" href="/assets/js/743.70a96283.js"><link rel="prefetch" href="/assets/js/744.909b870c.js"><link rel="prefetch" href="/assets/js/745.80defb2d.js"><link rel="prefetch" href="/assets/js/746.fb972248.js"><link rel="prefetch" href="/assets/js/747.1a7b52fd.js"><link rel="prefetch" href="/assets/js/748.036f5d16.js"><link rel="prefetch" href="/assets/js/749.bd9a413d.js"><link rel="prefetch" href="/assets/js/75.23c5a54d.js"><link rel="prefetch" href="/assets/js/750.3f1ae8f5.js"><link rel="prefetch" href="/assets/js/751.8897bc9f.js"><link rel="prefetch" href="/assets/js/752.9b387659.js"><link rel="prefetch" href="/assets/js/753.f411ce21.js"><link rel="prefetch" href="/assets/js/754.26def684.js"><link rel="prefetch" href="/assets/js/755.923aff62.js"><link rel="prefetch" href="/assets/js/756.9965743a.js"><link rel="prefetch" href="/assets/js/757.0c6bbbfd.js"><link rel="prefetch" href="/assets/js/758.a830f8b1.js"><link rel="prefetch" href="/assets/js/759.987cad77.js"><link rel="prefetch" href="/assets/js/760.9f2652a0.js"><link rel="prefetch" href="/assets/js/761.df01a0ee.js"><link rel="prefetch" href="/assets/js/762.e0c05a1a.js"><link rel="prefetch" href="/assets/js/763.da8a60bd.js"><link rel="prefetch" href="/assets/js/764.9f2a2830.js"><link rel="prefetch" href="/assets/js/765.44e61161.js"><link rel="prefetch" href="/assets/js/766.cd7da8c1.js"><link rel="prefetch" href="/assets/js/767.6ea1fea2.js"><link rel="prefetch" href="/assets/js/768.91529b8f.js"><link rel="prefetch" href="/assets/js/769.194d7a3e.js"><link rel="prefetch" href="/assets/js/77.3d43a163.js"><link rel="prefetch" href="/assets/js/770.227fd5b9.js"><link rel="prefetch" href="/assets/js/771.44d5e37e.js"><link rel="prefetch" href="/assets/js/772.234d9bf6.js"><link rel="prefetch" href="/assets/js/773.ff1dfb6a.js"><link rel="prefetch" href="/assets/js/774.d401364f.js"><link rel="prefetch" href="/assets/js/775.37a7cf41.js"><link rel="prefetch" href="/assets/js/776.0cd10853.js"><link rel="prefetch" href="/assets/js/777.599a3a48.js"><link rel="prefetch" href="/assets/js/778.eef27a95.js"><link rel="prefetch" href="/assets/js/779.29351199.js"><link rel="prefetch" href="/assets/js/78.fd0780ac.js"><link rel="prefetch" href="/assets/js/780.74caed94.js"><link rel="prefetch" href="/assets/js/781.ee0fa9b5.js"><link rel="prefetch" href="/assets/js/782.7cffed09.js"><link rel="prefetch" href="/assets/js/783.7f01f518.js"><link rel="prefetch" href="/assets/js/784.5f65e3d7.js"><link rel="prefetch" href="/assets/js/785.d7e13880.js"><link rel="prefetch" href="/assets/js/786.6110d12f.js"><link rel="prefetch" href="/assets/js/787.334a5cdd.js"><link rel="prefetch" href="/assets/js/788.f261bc71.js"><link rel="prefetch" href="/assets/js/789.b6d74f7d.js"><link rel="prefetch" href="/assets/js/79.7b5d6224.js"><link rel="prefetch" href="/assets/js/790.fa948ec4.js"><link rel="prefetch" href="/assets/js/791.22080013.js"><link rel="prefetch" href="/assets/js/792.31ce806c.js"><link rel="prefetch" href="/assets/js/793.9fd0c56f.js"><link rel="prefetch" href="/assets/js/794.44a8cd9c.js"><link rel="prefetch" href="/assets/js/795.9f8346e5.js"><link rel="prefetch" href="/assets/js/796.0de9c7a1.js"><link rel="prefetch" href="/assets/js/797.83ac32a6.js"><link rel="prefetch" href="/assets/js/798.393fc81d.js"><link rel="prefetch" href="/assets/js/799.c1fb3981.js"><link rel="prefetch" href="/assets/js/8.3275ed06.js"><link rel="prefetch" href="/assets/js/80.df3f0a1f.js"><link rel="prefetch" href="/assets/js/800.2832adeb.js"><link rel="prefetch" href="/assets/js/801.04c58fc4.js"><link rel="prefetch" href="/assets/js/81.3d90ef6b.js"><link rel="prefetch" href="/assets/js/82.2d42448d.js"><link rel="prefetch" href="/assets/js/83.900b4de2.js"><link rel="prefetch" href="/assets/js/84.ff570f67.js"><link rel="prefetch" href="/assets/js/85.e3b3af39.js"><link rel="prefetch" href="/assets/js/86.17b5aedc.js"><link rel="prefetch" href="/assets/js/87.f931d1d6.js"><link rel="prefetch" href="/assets/js/88.d55863cd.js"><link rel="prefetch" href="/assets/js/89.15a9a6d7.js"><link rel="prefetch" href="/assets/js/9.04948a9d.js"><link rel="prefetch" href="/assets/js/90.22696aa9.js"><link rel="prefetch" href="/assets/js/91.f1bd8a2e.js"><link rel="prefetch" href="/assets/js/92.85733094.js"><link rel="prefetch" href="/assets/js/93.59bacfd7.js"><link rel="prefetch" href="/assets/js/94.a5f9b7a0.js"><link rel="prefetch" href="/assets/js/95.be52d65a.js"><link rel="prefetch" href="/assets/js/96.0b76ba8e.js"><link rel="prefetch" href="/assets/js/97.28183cd4.js"><link rel="prefetch" href="/assets/js/98.2d22829c.js"><link rel="prefetch" href="/assets/js/99.ed602a20.js">
    <link rel="stylesheet" href="/assets/css/0.styles.a3df589e.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">AJ</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">主页</a></div><div class="nav-item"><a href="/op/" class="nav-link">Devops</a></div><div class="nav-item"><a href="/golang/" class="nav-link">Go</a></div><div class="nav-item"><a href="/go-block/" class="nav-link router-link-active">区块链</a></div><div class="nav-item"><a href="/k8s/" class="nav-link">k8s</a></div><div class="nav-item"><a href="/about.html" class="nav-link">关于我</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="更多" class="dropdown-title"><span class="title">更多</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/go-learning/" class="nav-link">go-learning</a></li><li class="dropdown-item"><!----> <a href="/post/flutter-guide/" class="nav-link">flutter</a></li><li class="dropdown-item"><!----> <a href="/mysql/" class="nav-link">mysql</a></li><li class="dropdown-item"><!----> <a href="/python/" class="nav-link">python</a></li></ul></div></div> <a href="https://github.com/ChinaArJun" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">主页</a></div><div class="nav-item"><a href="/op/" class="nav-link">Devops</a></div><div class="nav-item"><a href="/golang/" class="nav-link">Go</a></div><div class="nav-item"><a href="/go-block/" class="nav-link router-link-active">区块链</a></div><div class="nav-item"><a href="/k8s/" class="nav-link">k8s</a></div><div class="nav-item"><a href="/about.html" class="nav-link">关于我</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="更多" class="dropdown-title"><span class="title">更多</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/go-learning/" class="nav-link">go-learning</a></li><li class="dropdown-item"><!----> <a href="/post/flutter-guide/" class="nav-link">flutter</a></li><li class="dropdown-item"><!----> <a href="/mysql/" class="nav-link">mysql</a></li><li class="dropdown-item"><!----> <a href="/python/" class="nav-link">python</a></li></ul></div></div> <a href="https://github.com/ChinaArJun" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></nav> <div></div> <div style="padding-left:1.5rem;"><div></div></div> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>区块链基础</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/go-block/blockchain/encryption-expand.html" class="sidebar-link">常见的密码技术</a></li><li><a href="/go-block/blockchain/encryption.html" class="sidebar-link">密码学安全</a></li><li><a href="/go-block/blockchain/ethereum.html" class="sidebar-link">以太坊智能合约</a></li><li><a href="/go-block/blockchain/hyperledgerfabric.html" class="sidebar-link">hyperledger fabric</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Hyperledger Fabric 1.2</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/go-block/fabric/1搭建网络-纯手动.html" class="sidebar-link">1搭建网络-纯手动</a></li><li><a href="/go-block/fabric/1环境搭建.html" class="sidebar-link">1环境搭建</a></li><li><a href="/go-block/fabric/2Fabric介绍.html" class="sidebar-link">2Fabric介绍</a></li><li><a href="/go-block/fabric/3Fabric核心模块.html" class="sidebar-link">3Fabric核心模块</a></li><li><a href="/go-block/fabric/4网络搭建-脚本.html" class="sidebar-link">4网络搭建-脚本</a></li><li><a href="/go-block/fabric/5智能合约.html" class="sidebar-link">5智能合约</a></li><li><a href="/go-block/fabric/6Fabric账号.html" class="sidebar-link">6Fabric账号</a></li><li><a href="/go-block/fabric/7Solo多机多节点部署.html" class="sidebar-link">7Solo多机多节点部署</a></li><li><a href="/go-block/fabric/8Kafka多机多节点部署.html" class="sidebar-link">8Kafka多机多节点部署</a></li></ul></section></li><li><section class="sidebar-group depth-0"><p class="sidebar-heading"><span>Hyperledger Fabric 2.X</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/go-block/fabric2.x/" class="sidebar-link">2.X目录</a></li></ul></section></li></ul> </aside> <!----> <!----> <main class="page"><div class="theme-default-content" style="margin-bottom:-5rem;"><div class="bar"><div class="bar-intro"><div class="text">
      流逝的是岁月，不变的是情怀.
        </div> <div class="text">
      坚持学习，是为了成就更好的自己. <br></div> <div>公众号[中关村程序员]</div></div></div> <!----></div> <div class="theme-default-content content__default"><p>DOCKER</p> <p><img src="assets/dockerlogo.jpg" alt="dockerlogo"></p> <h1 id="第-1-章-docker基础"><a href="#第-1-章-docker基础" class="header-anchor">#</a> 第 1 章 Docker基础</h1> <h2 id="_1-1-docker简介"><a href="#_1-1-docker简介" class="header-anchor">#</a> 1.1 docker简介</h2> <p>在这一部分我们主要讲两个方面：
docker是什么、docker特点</p> <h3 id="_1-1-1-docker是什么"><a href="#_1-1-1-docker是什么" class="header-anchor">#</a> 1.1.1 docker是什么</h3> <h4 id="docker是什么？"><a href="#docker是什么？" class="header-anchor">#</a> docker是什么？</h4> <p>​	docker的中文解释是<strong>码头工人</strong>。</p> <p><strong>官方解释：</strong></p> <p>​	Docker是一个开源的容器引擎，它基于LCX容器技术，使用Go语言开发。</p> <p>​	源代码托管在Github上，并遵从Apache2.0协议。</p> <p>​	Docker采用C/S架构，其可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。</p> <p>​	Docker就是一种快速解决生产问题的一种技术手段,开发，运行和部署应用程序的开放管理平台。</p> <p>​	<strong>开发人员</strong>能利用docker 开发和运行应用程序</p> <p>​	<strong>运维人员</strong>能利用docker 部署和管理应用程序</p> <h4 id="docker的生活场景对比："><a href="#docker的生活场景对比：" class="header-anchor">#</a> Docker的生活场景对比：</h4> <table><thead><tr><th></th> <th></th></tr></thead> <tbody><tr><td>物理机</td> <td><img src="assets/%E7%8B%AC%E6%A0%8B%E5%88%AB%E5%A2%85.jpg" alt="独栋别墅"></td></tr> <tr><td>虚拟机</td> <td><img src="assets/%E5%85%AC%E5%AF%93%E4%BD%8F%E5%AE%85.jpg" alt="公寓住宅"></td></tr> <tr><td>容器是</td> <td><img src="assets/%E8%83%B6%E5%9B%8A%E5%85%AC%E5%AF%93.jpg" alt="胶囊公寓"></td></tr></tbody></table> <h4 id="单独的理解一下容器"><a href="#单独的理解一下容器" class="header-anchor">#</a> 单独的理解一下容器:</h4> <table><thead><tr><th>动画片《七龙珠》里面的胶囊</th> <th>1号胶囊启动后的效果</th></tr></thead> <tbody><tr><td><img src="assets/%E9%BE%99%E7%8F%A0%E8%83%B6%E5%9B%8A.jpg" alt="龙珠胶囊"></td> <td><img src="assets/%E5%AE%8C%E6%88%90%E4%BA%86.jpg" alt="完成了"></td></tr></tbody></table> <p>​	Docker提供了在一个完全隔离的环境中打包和运行应用程序的能力，这个隔离的环境被称为容器。</p> <p>​	由于容器的隔离性和安全性，因此可以在一个主机(宿主机)上同时运行多个相互隔离的容器，互不干预。</p> <h3 id="_1-1-2为什么使用docker"><a href="#_1-1-2为什么使用docker" class="header-anchor">#</a> 1.1.2为什么使用Docker</h3> <p>​	Docker使您能够将应用程序与基础架构分开，以便您可以快速交付软件。</p> <p>​	借助Docker，您可以像管理应用程序一样管理基础架构。</p> <p>​	通过利用Docker的方法快速进行运输，测试和部署代码，您可以显着缩短编写代码和在生产环境中运行代码之间的延迟。</p> <p><strong>例如:</strong>
​	开发人员在本地编写代码，可以使用Docker同事进行共享，实现协同工作。</p> <p>​	使用Docker开发完成程序，可以直接对应用程序执行自动和手动测试。</p> <p>​	当开发人员发现错误或BUG时，可以直接在开发环境中修复后，并迅速将它们重新部署到测试环境进行测试和验证。</p> <p>​	利用Docker开发完成后，交付时，直接交付Docker，也就意味着交付完成。后续如果有提供修补程序或更新，需要推送到生成环境运行起来，也是一样的简单。</p> <p><strong>Docker主要解决的问题：</strong></p> <p>​	保证程序运行环境的一致性；</p> <p>​	降低配置开发环境、生产环境的复杂度和成本；</p> <p>​	实现程序的快速部署和分发。</p> <h3 id="_1-1-3docker的架构与结构"><a href="#_1-1-3docker的架构与结构" class="header-anchor">#</a> 1.1.3Docker的架构与结构</h3> <p><strong>架构图</strong></p> <p><img src="assets/jg.png" alt="jg"></p> <p><strong>Docker</strong>是采用了(c/s)架构模式的应用程序</p> <p>Client dockerCLI :客户端docker命令行</p> <p>REST API : 一套介于客户端与服务端的之间进行通信并指示其执行的接口</p> <p>Server docker daemon:服务端dacker守护进程等待客户端发送命令来执行</p> <p><strong>Docker</strong>的四大核心技术</p> <p>镜像：一个Docker的可执行文件，其中包括运行应用程序所需的所有代码内容、依赖库、环境变量和配置文件等。</p> <p>容器：镜像被运行起来后的实例。</p> <p>网络：外部或者容器间如何互相访问的网络方式，如host模式、bridge模式。</p> <p>数据卷：容器与宿主机之间、容器与容器之间共享存储方式，类似虚拟机与主机之间的共享文件目录。</p> <p><strong>结构图</strong></p> <p><img src="assets/jiegou.png" alt="jiegou"></p> <ul><li><p>客户端 -&gt; 一个服务</p> <ul><li>一个守护进程, 通过shell终端可以进行一些操作</li></ul></li> <li><p>服务器 -&gt; 守护进程</p> <ul><li>接收客户端的请求</li> <li>管理容器, 管理镜像</li></ul></li> <li><p>docker镜像</p> <ul><li>一个可执行程序</li> <li>只占用硬盘资源</li></ul></li> <li><p>docker容器</p> <ul><li>镜像启动之后运行在docker容器中</li> <li>占用cpu和内存资源</li></ul></li> <li><p>docker仓库</p> <ul><li><p>存储镜像</p></li> <li><p>docker hub</p></li></ul></li></ul> <h3 id="_1-1-4官方资料："><a href="#_1-1-4官方资料：" class="header-anchor">#</a> 1.1.4官方资料：</h3> <p>Docker 官网：http://www.docker.com</p> <p>Github Docker 源码：https://github.com/docker/docker</p> <p>Docker 英文文档网址：https://docs.docker.com/</p> <p>Docker 中文文档网址：http://docker-doc.readthedocs.io/zh_CN/latest/</p> <h2 id="_1-2-docker快速入门"><a href="#_1-2-docker快速入门" class="header-anchor">#</a> 1.2 docker快速入门</h2> <h3 id="_1-2-1docker历程："><a href="#_1-2-1docker历程：" class="header-anchor">#</a> 1.2.1docker历程：</h3> <p>​	自2013年出现以来，发展势头很猛，现在可说是风靡全球。</p> <p>​	docker的第一版为0.1.0 发布于2013年03月23日</p> <p>​	Docker2017年改版前的版本号是1.13.1发布于2017年02月08日</p> <p>​	Docker从1.13.x版本开始，版本分为企业版EE和社区版CE，版本号也改为按照时间线来发布，比如17.03就是2017年3月，有点类似于ubuntu的版本发布方式。
​	企业版自然会提供一些额外的服务，当然肯定也是收费的。
​	企业版说明https://blog.docker.com/2017/03/docker-enterprise-edition/
社区版分为stable和edge两种发布方式。</p> <p>stable版本是季度发布方式，比如17.03, 17.06, 17.09</p> <p>edge版本是月份发布方式， 比如17.03, 17.04......</p> <h3 id="_1-2-2-官方要求"><a href="#_1-2-2-官方要求" class="header-anchor">#</a> 1.2.2 官方要求</h3> <p>为什么用ubuntu学docker</p> <p><img src="assets/docker%E4%B8%8Eubuntu%E6%94%AF%E6%8C%81.png" alt="docker与ubuntu支持"></p> <p>图片来源：https://docs.docker.com/engine/installation/#server</p> <p>docker要求的ubuntu环境</p> <p><img src="assets/ubuntu%E6%94%AF%E6%8C%81%E7%89%88%E6%9C%AC.png" alt="ubuntu支持版本"></p> <p>ubuntu下载地址：https://www.ubuntu.com/download/desktop</p> <h4 id="ubuntu主机环境需求"><a href="#ubuntu主机环境需求" class="header-anchor">#</a> ubuntu主机环境需求</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#执行命令</span>
$ <span class="token function">uname</span> -a
$ <span class="token function">ls</span> -l /sys/class/misc/device-mapper
</code></pre></div><h5 id="执行效果"><a href="#执行效果" class="header-anchor">#</a> 执行效果</h5> <p><img src="assets/docker%E7%8E%AF%E5%A2%83%E9%9C%80%E6%B1%82%E6%89%A7%E8%A1%8C%E6%95%88%E6%9E%9C.png" alt="docker环境需求执行效果"></p> <h3 id="_1-2-3-部署docker"><a href="#_1-2-3-部署docker" class="header-anchor">#</a> 1.2.3 部署docker</h3> <h4 id="官网参考："><a href="#官网参考：" class="header-anchor">#</a> 官网参考：</h4> <p>https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/#upgrade-docker-after-using-the-convenience-script</p> <h4 id="安装步骤"><a href="#安装步骤" class="header-anchor">#</a> 安装步骤</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#安装基本软件</span>
$ <span class="token function">sudo</span> <span class="token function">apt-get</span> update
$ <span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> apt-transport-https ca-certificates <span class="token function">curl</span> software-properties-common lrzsz -y
<span class="token comment">#使用官方推荐源{不推荐}#</span>
$ <span class="token function">sudo</span> <span class="token function">curl</span> -fsSL https://download.docker.com/linux/ubuntu/gpg <span class="token operator">|</span> <span class="token function">sudo</span> apt-key <span class="token function">add</span> -
add-apt-repository <span class="token string">&quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu <span class="token variable"><span class="token variable">$(</span>lsb_release -cs<span class="token variable">)</span></span> stable&quot;</span>
<span class="token comment">#使用阿里云的源{推荐}</span>
$ <span class="token function">sudo</span> <span class="token function">curl</span> -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg <span class="token operator">|</span> <span class="token function">sudo</span> apt-key <span class="token function">add</span> -
$ <span class="token function">sudo</span> add-apt-repository <span class="token string">&quot;deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu <span class="token variable"><span class="token variable">$(</span>lsb_release -cs<span class="token variable">)</span></span> stable&quot;</span>

<span class="token comment">#软件源升级</span>
$ <span class="token function">sudo</span> <span class="token function">apt-get</span> update

<span class="token comment">#安装docker</span>
$ <span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> docker-ce -y

<span class="token comment">#注：</span>
<span class="token comment">#可以指定版本安装docker：</span>
$ <span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> docker-ce<span class="token operator">=</span><span class="token operator">&lt;</span>VERSION<span class="token operator">&gt;</span> -y
  
<span class="token comment">#查看支持的docker版本</span>
$ <span class="token function">sudo</span> <span class="token function">apt-cache</span> madison docker-ce
<span class="token comment">#测试docker</span>
docker version
</code></pre></div><h4 id="网卡区别："><a href="#网卡区别：" class="header-anchor">#</a> 网卡区别：</h4> <p>安装前：只有ens33和lo网卡</p> <p><img src="assets/docker%E5%AE%89%E8%A3%85%E5%89%8D.png" alt="docker安装前"></p> <p>安装后：docker启动后，多出来了docker0网卡，网卡地址172.17.0.1</p> <p><img src="assets/docker%E5%AE%89%E8%A3%85%E5%90%8E.png" alt="docker安装后"></p> <h3 id="_1-2-4-docker加速器"><a href="#_1-2-4-docker加速器" class="header-anchor">#</a> 1.2.4 docker加速器</h3> <p>在国内使用docker的官方镜像源，会因为网络的原因，造成无法下载，或者一直处于超时。所以我们使用 daocloud的方法进行加速配置。
加速器文档链接：http://guide.daocloud.io/dcs/daocloud-9153151.html</p> <h4 id="方法"><a href="#方法" class="header-anchor">#</a> 方法:</h4> <p>访问 https://dashboard.daocloud.io 网站，登录 daocloud 账户</p> <p><img src="assets/doacloud%E7%99%BB%E5%BD%95.png" alt="doacloud登录"></p> <p>点击右上角的 加速器</p> <p><img src="assets/%E5%8A%A0%E9%80%9F%E5%99%A8.png" alt="加速器"></p> <p>在新窗口处会显示一条命令，</p> <p><img src="assets/%E5%8A%A0%E9%80%9F%E5%99%A8%E5%91%BD%E4%BB%A4.png" alt="加速器命令"></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#我们执行这条命令</span>
<span class="token function">curl</span> -sSL https://get.daocloud.io/daotools/set_mirror.sh <span class="token operator">|</span> <span class="token function">sh</span> -s http://f1361db2.m.daocloud.io

<span class="token comment">#修改daemon.json文件，增加</span>

, <span class="token string">&quot;insecure-registries&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>

<span class="token comment">#到大括号后</span>

<span class="token comment"># cat /etc/docker/daemon.json</span>


<span class="token punctuation">{</span><span class="token string">&quot;registry-mirrors&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span><span class="token string">&quot;http://f1361db2.m.daocloud.io&quot;</span><span class="token punctuation">]</span>, <span class="token string">&quot;insecure-registries&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">}</span>

<span class="token comment">#注意：</span>
<span class="token comment">#docker cloud加速器的默认内容是少了一条配置，所以我们要编辑文件把后面的内容补全</span>
<span class="token comment">#重启docker</span>
systemctl restart docker
</code></pre></div><h3 id="_1-2-5-docker-其他简介"><a href="#_1-2-5-docker-其他简介" class="header-anchor">#</a> 1.2.5 docker 其他简介</h3> <h4 id="docker的基本命令格式："><a href="#docker的基本命令格式：" class="header-anchor">#</a> docker的基本命令格式：</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#基本格式</span>
systemctl <span class="token punctuation">[</span>参数<span class="token punctuation">]</span> docker
<span class="token comment">#参数详解：</span>
	start         开启服务
    stop          关闭
    restart       重启
    status        状态
</code></pre></div><h4 id="删除docker命令："><a href="#删除docker命令：" class="header-anchor">#</a> 删除docker命令：</h4> <div class="language-shell extra-class"><pre class="language-shell"><code>$  <span class="token function">sudo</span> <span class="token function">apt-get</span> purge docker-ce -y
$  <span class="token function">sudo</span> <span class="token function">rm</span> -rf /etc/docker
$  <span class="token function">sudo</span> <span class="token function">rm</span> -rf /var/lib/docker/
</code></pre></div><h4 id="docker基本目录简介"><a href="#docker基本目录简介" class="header-anchor">#</a> docker基本目录简介:</h4> <div class="language-SHELL extra-class"><pre class="language-shell"><code>/etc/docker/                <span class="token comment">#docker的认证目录</span>
/var/lib/docker/            <span class="token comment">#docker的应用目录</span>
</code></pre></div><h4 id="docker常见bug"><a href="#docker常见bug" class="header-anchor">#</a> docker常见bug:</h4> <h5 id="背景"><a href="#背景" class="header-anchor">#</a> 背景</h5> <p>​	因为使用的是sudo安装docker，所以会导致一个问题。以普通用户登录的状况下，在使用docker images时必须添加sudo，那么如何让docker免sudo依然可用呢？</p> <h5 id="理清问题"><a href="#理清问题" class="header-anchor">#</a> 理清问题</h5> <p>​	当以普通用户身份去使用docker命令时，出现以下错误：</p> <div class="language-shell extra-class"><pre class="language-shell"><code>Got permission denied <span class="token keyword">while</span> trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post http://%2Fvar%2Frun%2Fdocker.sock/v1.35/images/create?fromSrc<span class="token operator">=</span>-<span class="token operator">&amp;</span><span class="token assign-left variable">message</span><span class="token operator">=</span><span class="token operator">&amp;</span><span class="token assign-left variable">repo</span><span class="token operator">=</span>ubuntu-16.04<span class="token operator">&amp;</span><span class="token assign-left variable">tag</span><span class="token operator">=</span>: dial unix /var/run/docker.sock: connect: permission denied
</code></pre></div><p>​	可以看都，最后告知我们时权限的问题。那么在linux文件权限有三个数据左右drwxrwxrwx，其中第一为d代表该文件是一个文件夹前三位、中三位、后三位分别代表这属主权限、属组权限、其他人权限。</p> <p><img src="assets/dockersock%E6%9D%83%E9%99%90.png" alt="dockersock权限"></p> <p>​	上图是报错文件的权限展示，可以看到其属主为root，权限为rw，可读可写；其属组为docker，权限为rw，可读可写。如果要当前用户可直接读取该文件，那么我们就为docker.sock 添加一个其他用户可读写权限 或者添加1个用户组就可以了</p> <h5 id="方法1：一劳永逸"><a href="#方法1：一劳永逸" class="header-anchor">#</a> 方法1：一劳永逸</h5> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#如果还没有 docker group 就添加一个：</span>
<span class="token variable">$sudo</span> <span class="token function">groupadd</span> docker
<span class="token comment">#将用户加入该 group 内。然后退出并重新登录就生效啦。</span>
<span class="token variable">$sudo</span> gpasswd -a <span class="token variable">${<span class="token environment constant">USER</span>}</span> docker
<span class="token comment">#重启 docker 服务</span>
<span class="token variable">$systemctl</span> restart docker
<span class="token comment">#切换当前会话到新 group 或者重启 X 会话</span>
<span class="token variable">$newgrp</span> - docker
<span class="token comment">#注意:最后一步是必须的，否则因为 groups 命令获取到的是缓存的组信息，刚添加的组信息未能生效，</span>
<span class="token comment">#所以 docker images 执行时同样有错。</span>
</code></pre></div><h5 id="方法2："><a href="#方法2：" class="header-anchor">#</a> 方法2：</h5> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#每次启动docker或者重启docker的之后</span>
<span class="token variable">$cd</span> /var/run
<span class="token variable">$sudo</span> <span class="token function">chmod</span> <span class="token number">666</span> docker.sock
</code></pre></div><h5 id="方法3：每条命令前面加上sudo"><a href="#方法3：每条命令前面加上sudo" class="header-anchor">#</a> 方法3：每条命令前面加上sudo</h5> <p><img src="assets/%E5%90%83%E9%B2%B8.jpg" alt="吃鲸">.AVI</p> <h1 id="第-2-章-docker-核心技术"><a href="#第-2-章-docker-核心技术" class="header-anchor">#</a> 第 2 章 Docker 核心技术</h1> <p>Docker的核心技术内容很多，我们学习则从以下四个方面来介绍Docker的核心技术
<strong>镜像</strong>、<strong>容器</strong>、<strong>数据</strong>、<strong>网络</strong></p> <h2 id="_2-1-docker镜像管理"><a href="#_2-1-docker镜像管理" class="header-anchor">#</a> 2.1 docker镜像管理</h2> <h3 id="_2-1-1-镜像简介"><a href="#_2-1-1-镜像简介" class="header-anchor">#</a> 2.1.1 镜像简介</h3> <p>Docker镜像是什么？
​	镜像是一个Docker的可执行文件，其中包括运行应用程序所需的所有代码内容、依赖库、环境变量和配置文件等。
​	通过镜像可以创建一个或多个容器。</p> <h3 id="_2-1-2-搜索、查看、获取"><a href="#_2-1-2-搜索、查看、获取" class="header-anchor">#</a> 2.1.2 搜索、查看、获取</h3> <h4 id="搜索镜像"><a href="#搜索镜像" class="header-anchor">#</a> 搜索镜像</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用</span>
	搜索Docker Hub<span class="token punctuation">(</span>镜像仓库<span class="token punctuation">)</span>上的镜像
<span class="token comment">#命令格式：</span>
    docker search <span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>
<span class="token comment">#命令演示：</span>
$ docker search ubuntu
<span class="token comment">#NAME：名称</span>
<span class="token comment">#DESCRIPTION：基本功能描述</span>
<span class="token comment">#STARS：星级（收到关注程度）</span>
<span class="token comment">#OFFICIAL：是否官方创建</span>
<span class="token comment">#AUTOMATED：是否自动创建</span>
</code></pre></div><h4 id="获取镜像"><a href="#获取镜像" class="header-anchor">#</a> 获取镜像</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	下载远程仓库（如Docker Hub）中的镜像
<span class="token comment">#命令格式：</span>
docker pull <span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>
<span class="token comment">#命令演示：</span>
$ docker pull ubuntu
$ docker pull nginx

<span class="token comment">#注释：</span>
<span class="token comment">#获取的镜像在哪里？</span>
<span class="token comment">#/var/lib/docker 目录下</span>

<span class="token comment">#由于权限的原因我们需要切换root用户</span>
<span class="token comment">#那我们首先要重设置root用户的密码：</span>
:~$ <span class="token function">sudo</span> <span class="token function">passwd</span> root
<span class="token comment">#这样就可以设置root用户的密码了。</span>
<span class="token comment">#之后就可以自由的切换到root用户了</span>
:~$ <span class="token function">su</span>
<span class="token comment">#输入root用户的密码即可。</span>

<span class="token comment">#当然，如果想从root用户切换回一般用户，则可使用 su -val(一般用户名)</span>
<span class="token comment">#而当你再次切回到root用户，则只需要键入exit,再次输入exit则回到最初的用户下</span>
<span class="token comment">#操作下面的文件可以查看相关的镜像信息       </span>
:~$ <span class="token function">vim</span> /var/lib/docker/image/overlay2/repositories.json 
<span class="token comment">#文件所在</span>
:~$ <span class="token builtin class-name">pwd</span>
/var/lib/docker/image/overlay2/imagedb/content/sha256

</code></pre></div><h4 id="查看镜像"><a href="#查看镜像" class="header-anchor">#</a> 查看镜像</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
   列出本地镜像
<span class="token comment">#命令格式：</span>
docker images <span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>
docker image <span class="token function">ls</span> <span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>
<span class="token comment">#命令演示：</span>
$ docker images
<span class="token comment">#镜像的ID唯一标识了镜像，如果ID相同,说明是同一镜像。TAG信息来区分不同发行版本，如果不指定具体标记,默认使用latest标记信息</span>
<span class="token comment">#docker images -a 列出所有的本地的images(包括已删除的镜像记录)</span>
<span class="token comment">#REPOSITORY：镜像的名称 </span>
<span class="token comment">#TAG ：镜像的版本标签</span>
<span class="token comment">#IMAGE ID：镜像id</span>
<span class="token comment">#CREATED：镜像是什么时候创建的</span>
<span class="token comment">#SIZE：大小</span>
</code></pre></div><h3 id="_2-1-3-重命名、删除"><a href="#_2-1-3-重命名、删除" class="header-anchor">#</a> 2.1.3 重命名、删除</h3> <h4 id="镜像重命名"><a href="#镜像重命名" class="header-anchor">#</a> 镜像重命名</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	对本地镜像的NAME、TAG进行重命名，并新产生一个命名后镜像
<span class="token comment">#命令格式：</span>
docker tag <span class="token punctuation">[</span>老镜像名称<span class="token punctuation">]</span>:<span class="token punctuation">[</span>老镜像版本<span class="token punctuation">]</span><span class="token punctuation">[</span>新镜像名称<span class="token punctuation">]</span>:<span class="token punctuation">[</span>新镜像版本<span class="token punctuation">]</span>
<span class="token comment">#命令演示：</span>
$ docker tag nginx:latest panda-nginx:v1.0
</code></pre></div><h4 id="删除镜像"><a href="#删除镜像" class="header-anchor">#</a> 删除镜像</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	将本地的一个或多个镜像删除
<span class="token comment">#命令格式：</span>
docker rmi <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像ID<span class="token punctuation">]</span>
docker rmi <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>:<span class="token punctuation">[</span>镜像版本<span class="token punctuation">]</span>
docker image <span class="token function">rm</span> <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像<span class="token punctuation">]</span>
<span class="token comment">#命令演示：</span>
<span class="token variable">$docker</span> rmi 3fa822599e10
<span class="token variable">$docker</span> rmi mysql:latest
<span class="token comment">#注意：</span>
如果一个image_id存在多个名称，那么应该使用 名称:版本 的格式删除镜像
<span class="token comment">#命令参数(OPTIONS)：	</span>
	-f, --force      		强制删除
</code></pre></div><h3 id="_2-1-4-导出、导入"><a href="#_2-1-4-导出、导入" class="header-anchor">#</a> 2.1.4 导出、导入</h3> <h4 id="导出镜像"><a href="#导出镜像" class="header-anchor">#</a> 导出镜像</h4> <p>将已经下载好的镜像，导出到本地，以备后用。</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	将本地的一个或多个镜像打包保存成本地tar文件
<span class="token comment">#命令格式：</span>
docker save <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span><span class="token punctuation">[</span>导出镜像名称<span class="token punctuation">]</span><span class="token punctuation">[</span>本地镜像名称<span class="token punctuation">]</span>
<span class="token comment">#命令参数(OPTIONS)：	</span>
	-o, --output string   		指定写入的文件名和路径
<span class="token comment">#导出镜像</span>
:~$ docker save -o nginx.tar nginx
</code></pre></div><h4 id="导入镜像"><a href="#导入镜像" class="header-anchor">#</a> 导入镜像</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	将save命令打包的镜像导入本地镜像库中
<span class="token comment">#导入镜像命令格式：</span>
$ docker load <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span><span class="token punctuation">[</span>被导入镜像压缩文件的名称<span class="token punctuation">]</span>
$ docker load <span class="token operator">&lt;</span> <span class="token punctuation">[</span>被导入镜像压缩文件的名称<span class="token punctuation">]</span>
$ docker load --input <span class="token punctuation">[</span>被导入镜像压缩文件的名称<span class="token punctuation">]</span>
<span class="token comment">#命令参数(OPTIONS)：	</span>
	-i,  --input string   	指定要打入的文件，如没有指定，默认是STDIN
	
<span class="token comment">#为了更好的演示效果，我们先将nginx的镜像删除掉</span>
docker rmi nginx:v1.0
docker rmi nginx    

<span class="token comment">#导入镜像文件：</span>
$ docker load <span class="token operator">&lt;</span> nginx.tar
<span class="token comment">#注意：</span>
	如果发现导入的时候没有权限需要使用chmod命令修改镜像文件的权限
</code></pre></div><h3 id="_2-1-5-历史、详细信息、创建"><a href="#_2-1-5-历史、详细信息、创建" class="header-anchor">#</a> 2.1.5 历史、详细信息、创建</h3> <h4 id="查看镜像历史"><a href="#查看镜像历史" class="header-anchor">#</a> 查看镜像历史</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	查看本地一个镜像的历史<span class="token punctuation">(</span>历史分层<span class="token punctuation">)</span>信息
<span class="token comment">#查看镜像命令格式：</span>
docker <span class="token function">history</span> <span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>:<span class="token punctuation">[</span>镜像版本<span class="token punctuation">]</span>
docker <span class="token function">history</span> <span class="token punctuation">[</span>镜像ID<span class="token punctuation">]</span>
<span class="token comment">#我们获取到一个镜像，想知道他默认启动了哪些命令或者都封装了哪些系统层，那么我们可以使用docker history这条命令来获取我们想要的信息</span>
$ docker <span class="token function">history</span> sswang-nginx:v1.0
 
<span class="token comment">#IMAGE：编号           </span>
<span class="token comment">#CREATED：创建的  </span>
<span class="token comment">#CREATED BY ：基于那些命令创建的                                 </span>
<span class="token comment">#SIZE：大小</span>
<span class="token comment">#COMMENT：评论</span>
</code></pre></div><h4 id="镜像详细信息"><a href="#镜像详细信息" class="header-anchor">#</a> 镜像详细信息</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	查看本地一个或多个镜像的详细信息
<span class="token comment">#命令格式：</span>
$ docker image inspect <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span> <span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>:<span class="token punctuation">[</span>镜像版本<span class="token punctuation">]</span>
$ docker inspect <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span> <span class="token punctuation">[</span>镜像ID<span class="token punctuation">]</span>
<span class="token comment">#查看镜像详细信息：</span>
$ docker inspect nginx
</code></pre></div><h4 id="根据模板创建镜像"><a href="#根据模板创建镜像" class="header-anchor">#</a> 根据模板创建镜像</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#登录系统模板镜像网站：  </span>
<span class="token comment">#https://download.openvz.org/template/precreated/</span>
<span class="token comment">#找到一个镜像模板进行下载，比如说ubuntu-16.04-x86_64.tar.gz，地址为：</span>
<span class="token comment">#https://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz    </span>
<span class="token comment">#命令格式：</span>
<span class="token function">cat</span> 模板文件名.tar <span class="token operator">|</span> docker <span class="token function">import</span> - <span class="token punctuation">[</span>自定义镜像名<span class="token punctuation">]</span>
<span class="token comment">#演示效果：</span>
$ <span class="token function">cat</span> ubuntu-16.04-x86_64.tar.gz <span class="token operator">|</span> docker <span class="token function">import</span> - ubuntu-mini
</code></pre></div><h3 id="_2-1-6总结"><a href="#_2-1-6总结" class="header-anchor">#</a> 2.1.6总结</h3> <p><img src="assets/1541570009278.png" alt="1541570009278"></p> <h2 id="_2-2-容器管理"><a href="#_2-2-容器管理" class="header-anchor">#</a> 2.2 容器管理</h2> <p>​	docker容器技术指Docker是一个由GO语言写的程序运行的“容器”（Linux containers， LXCs）</p> <p>​       containers的中文解释是集装箱。</p> <p>​    Docker则实现了一种应用程序级别的隔离，它改变我们基本的开发、操作单元，由直接操作虚拟主机（VM）,转换到操作程序运行的“容器”上来。</p> <h3 id="_2-2-1-容器简介"><a href="#_2-2-1-容器简介" class="header-anchor">#</a> 2.2.1 容器简介</h3> <h4 id="容器是什么？"><a href="#容器是什么？" class="header-anchor">#</a> 容器是什么？</h4> <p>​	容器（Container）：容器是一种轻量级、可移植、并将应用程序进行的打包的技术，使应用程序可以在几乎任何地方以相同的方式运行</p> <p>​	•Docker将镜像文件运行起来后，产生的对象就是容器。容器相当于是镜像运行起来的一个实例。</p> <p>​	•容器具备一定的生命周期。</p> <p>​	•另外，可以借助docker ps命令查看运行的容器，如同在linux上利用ps命令查看运行着的进程那样。</p> <p>​	我们就可以理解容器就是被封装起来的进程操作,只不过现在的进程可以简单也可以复杂,复杂的话可以运行1个操作系统.简单的话可以运行1个回显字符串.</p> <h4 id="容器与虚拟机的相同点"><a href="#容器与虚拟机的相同点" class="header-anchor">#</a> 容器与虚拟机的相同点</h4> <p>•容器和虚拟机一样，都会对物理硬件资源进行共享使用。</p> <p>•容器和虚拟机的生命周期比较相似（创建、运行、暂停、关闭等等）。</p> <p>•容器中或虚拟机中都可以安装各种应用，如redis、mysql、nginx等。也就是说，在容器中的操作，如同在一个虚拟机(操作系统)中操作一样。</p> <p>•同虚拟机一样，容器创建后，会存储在宿主机上：linux上位于/var/lib/docker/containers下</p> <h4 id="容器与虚拟机的不同点"><a href="#容器与虚拟机的不同点" class="header-anchor">#</a> 容器与虚拟机的不同点</h4> <p><strong>注意</strong>：容器并不是虚拟机，但它们有很多相似的地方</p> <p>•虚拟机的创建、启动和关闭都是基于一个完整的操作系统。一个虚拟机就是一个完整的操作系统。而容器直接运行在宿主机的内核上，其本质上以一系列进程的结合。</p> <p>•容器是轻量级的，虚拟机是重量级的。</p> <p>​	首先容器不需要额外的资源来管理，虚拟机额外更多的性能消耗；</p> <p>​	其次创建、启动或关闭容器，如同创建、启动或者关闭进程那么轻松，而创建、启动、关闭一个操作系统就没那么方便了。</p> <p>•也因此，意味着在给定的硬件上能运行更多数量的容器，甚至可以直接把Docker运行在虚拟机上。</p> <h3 id="_2-2-2-查看、创建、启动"><a href="#_2-2-2-查看、创建、启动" class="header-anchor">#</a> 2.2.2 查看、创建、启动</h3> <h4 id="查看容器"><a href="#查看容器" class="header-anchor">#</a> 查看容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用</span>
	显示docker容器列表
<span class="token comment">#命令格式：</span>
docker <span class="token function">ps</span>
<span class="token comment">#命令演示：</span>
$ docker <span class="token function">ps</span>
<span class="token comment">#CONTAINER ID 容器ID        </span>
<span class="token comment">#IMAGE 基于那个镜像              </span>
<span class="token comment">#COMMAND  运行镜像使用了哪些命令？           </span>
<span class="token comment">#CREATED多久前创建时间             </span>
<span class="token comment">#STATUS   开启还是关闭           </span>
<span class="token comment">#PORTS端口号               </span>
<span class="token comment">#NAMES容器名称默认是随机的</span>
<span class="token comment">#注意：</span>
管理docker容器可以通过名称，也可以通过ID
ps是显示正在运行的容器， -a是显示所有运行过的容器，包括已经不运行的容器
</code></pre></div><h4 id="创建待启动容器"><a href="#创建待启动容器" class="header-anchor">#</a> 创建待启动容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	利用镜像创建出一个Created 状态的待启动容器
<span class="token comment">#命令格式：</span>
	docker create <span class="token punctuation">[</span>OPTIONS<span class="token punctuation">]</span> IMAGE <span class="token punctuation">[</span>COMMAND<span class="token punctuation">]</span> <span class="token punctuation">[</span>ARG<span class="token punctuation">..</span>.<span class="token punctuation">]</span>
	docker create <span class="token punctuation">[</span>参数命令<span class="token punctuation">]</span> 依赖镜像 <span class="token punctuation">[</span>容器内命令<span class="token punctuation">]</span> <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span>
<span class="token comment">#命令参数(OPTIONS)：查看更多</span>
	-t, --tty           		分配一个伪TTY，也就是分配虚拟终端
    -i, --interactive    	    即使没有连接，也要保持STDIN打开
        --name          		为容器起名，如果没有指定将会随机产生一个名称
<span class="token comment">#命令参数（COMMAND\ARG）:</span>
	COMMAND 表示容器启动后，需要在容器中执行的命令，如ps、ls 等命令
	ARG 表示执行 COMMAND 时需要提供的一些参数，如ps 命令的 aux、ls命令的-a等等
<span class="token comment">#创建容器（附上ls命令和a参数）</span>
	docker create -it --name ubuntu-1  ubuntu <span class="token function">ls</span> -a
</code></pre></div><p><strong>启动容器</strong></p> <p>启动容器有三种方式</p> <p>1、启动待启动或已关闭容器</p> <p>2、基于镜像新建一个容器并启动</p> <p>3、守护进程方式启动docker</p> <h4 id="启动容器"><a href="#启动容器" class="header-anchor">#</a> 启动容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	将一个或多个处于创建状态或关闭状态的容器启动起来

<span class="token comment">#命令格式：</span>
docker start <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器ID<span class="token punctuation">]</span>
<span class="token comment">#命令参数(OPTIONS)：</span>
	-a, --attach		将当前shell的 STDOUT/STDERR 连接到容器上
	-i, --interactive		将当前shell的 STDIN连接到容器上	
<span class="token comment">#启动上面创建的容器 </span>
	docker start -a ubuntu-1
</code></pre></div><h4 id="创建新容器并启动"><a href="#创建新容器并启动" class="header-anchor">#</a> 创建新容器并启动</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	利用镜像创建并启动一个容器
<span class="token comment">#命令格式：</span>
docker run <span class="token punctuation">[</span>命令参数<span class="token punctuation">]</span>  <span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span><span class="token punctuation">[</span>执行的命令<span class="token punctuation">]</span>
命令参数<span class="token punctuation">(</span>OPTIONS<span class="token punctuation">)</span>：
	-t, --tty           	分配一个伪TTY，也就是分配虚拟终端
    -i, --interactive    	即使没有连接，也要保持STDIN打开
        --name          	为容器起名，如果没有指定将会随机产生一个名称
	-d, --detach			在后台运行容器并打印出容器ID
	--rm					当容器退出运行后，自动删除容器

<span class="token comment">#启动一个镜像输出内容并删除容器</span>
$ docker run --rm  --name nginx1   nginx  /bin/echo <span class="token string">&quot;hello docker&quot;</span> 


<span class="token comment">#注意：</span>
docker run 其实 是两个命令的集合体 docker create + docker start
</code></pre></div><h4 id="守护进程方式启动容器-常用的方式"><a href="#守护进程方式启动容器-常用的方式" class="header-anchor">#</a> 守护进程方式启动容器&lt;常用的方式&gt;</h4> <p>更多的时候，需要让Docker容器在后台以守护形式运行。此时可以通过添加-d参数来实现</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker run -d <span class="token punctuation">[</span>image_name<span class="token punctuation">]</span> <span class="token builtin class-name">command</span> <span class="token punctuation">..</span>.
<span class="token comment">#守护进程方式启动容器:</span>
:~$ docker run -d nginx
</code></pre></div><h3 id="_2-2-3暂停与取消暂停与重启"><a href="#_2-2-3暂停与取消暂停与重启" class="header-anchor">#</a> 2.2.3暂停与取消暂停与重启</h3> <h4 id="容器暂停"><a href="#容器暂停" class="header-anchor">#</a> 容器暂停</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	暂停一个或多个处于运行状态的容器
<span class="token comment">#命令格式：</span>
	docker pause <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器ID<span class="token punctuation">]</span>
<span class="token comment">#暂停容器</span>
	docker pause a229eabf1f32 

</code></pre></div><h4 id="容器取消暂停"><a href="#容器取消暂停" class="header-anchor">#</a> 容器取消暂停</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	取消一个或多个处于暂停状态的容器，恢复运行
<span class="token comment">#命令格式：</span>
	docker unpause <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器ID<span class="token punctuation">]</span>
<span class="token comment">#恢复容器</span>
	docker unpause a229eabf1f32
</code></pre></div><h4 id="重启"><a href="#重启" class="header-anchor">#</a> 重启</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	重启一个或多个处于运行状态、暂停状态、关闭状态或者新建状态的容器
	该命令相当于stop和start命令的结合
<span class="token comment">#命令格式：</span>
	docker restart <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器ID<span class="token punctuation">]</span>
<span class="token comment">#命令参数(OPTIONS)：</span>
	 -t, --time int   		重启前，等待的时间，单位秒<span class="token punctuation">(</span>默认 10s<span class="token punctuation">)</span> 

<span class="token comment">#恢复容器</span>
	docker restart -t <span class="token number">20</span> a229eabf1f32
</code></pre></div><h3 id="_2-2-4-关闭、终止、删除"><a href="#_2-2-4-关闭、终止、删除" class="header-anchor">#</a> 2.2.4 关闭、终止、删除</h3> <h4 id="关闭容器"><a href="#关闭容器" class="header-anchor">#</a> 关闭容器</h4> <p>在生产中，我们会以为临时情况，要关闭某些容器，我们使用 stop 命令来关闭某个容器</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	延迟关闭一个或多个处于暂停状态或者运行状态的容器
<span class="token comment">#命令格式：</span>
  docker stop <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器ID<span class="token punctuation">]</span>

<span class="token comment">#关闭容器:</span>
$ docker stop  8005c40a1d16
</code></pre></div><h4 id="终止容器"><a href="#终止容器" class="header-anchor">#</a> 终止容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	强制并立即关闭一个或多个处于暂停状态或者运行状态的容器
<span class="token comment">#命令格式：</span>
	docker <span class="token function">kill</span> <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器ID<span class="token punctuation">]</span>
<span class="token comment">#终止容器</span>
$ docker <span class="token function">kill</span>  8005c40a1d16
</code></pre></div><h4 id=""><a href="#" class="header-anchor">#</a></h4> <h4 id="删除容器"><a href="#删除容器" class="header-anchor">#</a> 删除容器</h4> <p>删除容器有三种方法：
正常删除    --        删除已关闭的</p> <p>强制删除    --        删除正在运行的</p> <p>强制批量删除 --        删除全部的容器</p> <h5 id="正常删除容器"><a href="#正常删除容器" class="header-anchor">#</a> 正常删除容器</h5> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	删除一个或者多个容器

<span class="token comment">#命令格式：</span>
$ docker <span class="token function">rm</span> <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器ID<span class="token punctuation">]</span>   
<span class="token comment">#删除已关闭的容器:</span>
$ docker <span class="token function">rm</span> 1a5f6a0c9443
</code></pre></div><div class="language- extra-class"><pre class="language-text"><code>Error response from daemon: You cannot remove a running container c7f5e7fe5aca00e0cb987d486dab3502ac93d7180016cfae9ddcc64e56149fc9. Stop the container before attempting removal or force remove
错误响应守护进程:你不能删除一个容器c7f5e7fe5aca00e0cb987d486dab3502ac93d7180016cfae9ddcc64e56149fc9运行。在尝试拆卸或强制拆卸之前，先停止容器。
</code></pre></div><h5 id="强制删除运行容器"><a href="#强制删除运行容器" class="header-anchor">#</a> 强制删除运行容器</h5> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	强制删除一个或者多个容器
<span class="token comment">#命令格式：</span>
  docker <span class="token function">rm</span> -f <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器ID<span class="token punctuation">]</span>
<span class="token comment">#删除正在运行的容器</span>
$ docker <span class="token function">rm</span> -f 8005c40a1d16
</code></pre></div><p><img src="assets/%E5%89%8D%E6%96%B9%E9%AB%98%E8%83%BD.png" alt="前方高能"></p> <h5 id="拓展批量关闭容器"><a href="#拓展批量关闭容器" class="header-anchor">#</a> 拓展批量关闭容器</h5> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	批量强制删除一个或者多个容器
<span class="token comment">#命令格式：</span>
$ docker <span class="token function">rm</span> -f <span class="token variable"><span class="token variable">$(</span>docker <span class="token function">ps</span> -a -q<span class="token variable">)</span></span>
<span class="token comment">#按照执行顺序$（）， 获取到现在容器的id然后进行删除</span>
</code></pre></div><h3 id="_2-2-5-进入、退出"><a href="#_2-2-5-进入、退出" class="header-anchor">#</a> 2.2.5 进入、退出</h3> <p><strong>进入容器我们学习三种方法：</strong></p> <p>1、创建容器的同时进入容器
2、手工方式进入容器
3、生产方式进入容器</p> <h4 id="创建并进入容器"><a href="#创建并进入容器" class="header-anchor">#</a> 创建并进入容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker run --name <span class="token punctuation">[</span>container_name<span class="token punctuation">]</span> -it <span class="token punctuation">[</span>docker_image<span class="token punctuation">]</span> /bin/bash

<span class="token comment">#命令演示：</span>
$  docker run -it --name panda-nginx nginx /bin/bash
<span class="token comment">#进入容器后</span>
root@7c5a24a68f96:/<span class="token comment"># echo &quot;hello world&quot;</span>
hello world

root@7c5a24a68f96:/<span class="token comment"># exit</span>
<span class="token builtin class-name">exit</span>        
 
<span class="token comment">#docker 容器启动命令参数详解：</span>
<span class="token comment">#--name:给容器定义一个名称</span>
<span class="token comment">#-i:则让容器的标准输入保持打开。</span>
<span class="token comment">#-t:让docker分配一个伪终端,并绑定到容器的标准输入上</span>
<span class="token comment">#/bin/bash:执行一个命令</span>
</code></pre></div><h4 id="退出容器："><a href="#退出容器：" class="header-anchor">#</a> 退出容器：</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#方法一：</span>
<span class="token builtin class-name">exit</span>
<span class="token comment">#方法二：</span>
Ctrl + D
</code></pre></div><h4 id="手工方式进入容器"><a href="#手工方式进入容器" class="header-anchor">#</a> 手工方式进入容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker <span class="token builtin class-name">exec</span> -it  容器id  /bin/bash
<span class="token comment">#效果演示：</span>
$ docker <span class="token builtin class-name">exec</span> -it d74fff341687 /bin/bash
</code></pre></div><h4 id="生产方式进入容器"><a href="#生产方式进入容器" class="header-anchor">#</a> 生产方式进入容器</h4> <p>我们生产中常用的进入容器方法是使用脚本，脚本内容如下</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token shebang important">#!/bin/bash</span>

<span class="token comment">#定义进入仓库函数</span>
<span class="token function-name function">docker_in</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
  <span class="token assign-left variable">NAME_ID</span><span class="token operator">=</span><span class="token variable">$1</span>
  <span class="token assign-left variable">PID</span><span class="token operator">=</span><span class="token variable"><span class="token variable">$(</span>docker inspect --format <span class="token punctuation">{</span><span class="token punctuation">{</span>.State.Pid<span class="token punctuation">}</span><span class="token punctuation">}</span> $NAME_ID<span class="token variable">)</span></span>
  nsenter --target <span class="token variable">$PID</span> --mount --uts --ipc --net --pid
<span class="token punctuation">}</span>
docker_in <span class="token variable">$1</span>
</code></pre></div><p>直接执行的话是没有执行权限的所以需要赋值权限</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#赋权执行</span>
$  <span class="token function">chmod</span> +x docker_in.sh 
<span class="token comment">#进入指定的容器，并测试</span>
$  ./docker_in.sh b3fbcba852fd
</code></pre></div><h4 id="注意："><a href="#注意：" class="header-anchor">#</a> 注意：</h4> <table><thead><tr><th>当拷贝到linux下的时候会出现</th></tr></thead> <tbody><tr><td>-bash: ./docker_in.sh: /bin/bash^M: 解释器错误: 没有那个文件或目录<br>这个问题大多数是因为你的脚本文件在windows下编辑过。windows下，每一行的结尾是\n\r，而在linux下文件的结尾是\n，那么你在windows下编辑过的文件在linux下打开看的时候每一行的结尾就会多出来一个字符\r,用cat -A docker_in.sh时你可以看到这个\r字符被显示为^M，这时候只需要删除这个字符就可以了。<br>可以使用命令   sed -i 's/\r$//' docker_in.sh</td></tr></tbody></table> <h3 id="_2-2-6-基于容器创建镜像"><a href="#_2-2-6-基于容器创建镜像" class="header-anchor">#</a> 2.2.6 基于容器创建镜像</h3> <h4 id="方式一："><a href="#方式一：" class="header-anchor">#</a> 方式一：</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker commit -m <span class="token string">'改动信息'</span> -a <span class="token string">&quot;作者信息&quot;</span> <span class="token punctuation">[</span>container_id<span class="token punctuation">]</span><span class="token punctuation">[</span>new_image:tag<span class="token punctuation">]</span>
<span class="token comment">#命令演示：</span>
<span class="token comment">#进入一个容器，创建文件后并退出:</span>
$ ./docker_in.sh d74fff341687
$ <span class="token function">mkdir</span> /hello
$ <span class="token function">mkdir</span> /world
$ <span class="token function">ls</span>
$ <span class="token builtin class-name">exit</span>
<span class="token comment">#创建一个镜像:</span>
$ docker commit -m <span class="token string">'mkdir /hello /world '</span> -a <span class="token string">&quot;panda&quot;</span>  d74fff341687  nginx:v0.2
<span class="token comment">#查看镜像:</span>
$ docker images
<span class="token comment">#启动一个容器</span>
$ docker run -itd  nginx:v0.2 /bin/bash
<span class="token comment">#进入容器进行查看</span>
$ ./docker_in.sh ae63ab299a84
$ <span class="token function">ls</span>
</code></pre></div><h4 id="方式二"><a href="#方式二" class="header-anchor">#</a> 方式二:</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker <span class="token builtin class-name">export</span> <span class="token punctuation">[</span>容器id<span class="token punctuation">]</span> <span class="token operator">&gt;</span> 模板文件名.tar
<span class="token comment">#命令演示：</span>
<span class="token comment">#创建镜像:</span>
$ docker <span class="token builtin class-name">export</span> ae63ab299a84 <span class="token operator">&gt;</span> nginx.tar
<span class="token comment">#导入镜像:</span>
$ <span class="token function">cat</span> nginx.tar <span class="token operator">|</span> docker <span class="token function">import</span> - panda-test
</code></pre></div><table><thead><tr><th>导出（export）导入（import）与保存（save）加载（load）的恩怨情仇</th></tr></thead> <tbody><tr><td>import与load的区别：<br>import可以重新指定镜像的名字，docker load不可以</td></tr> <tr><td>export 与 保存 save 的区别：<br>1、export导出的镜像文件大小，小于 save保存的镜像。<br>2、export 导出（import导入）是根据容器拿到的镜像，再导入时会丢失镜像所有的历史。</td></tr></tbody></table> <h3 id="_2-2-7-日志、信息、端口、重命名"><a href="#_2-2-7-日志、信息、端口、重命名" class="header-anchor">#</a> 2.2.7 日志、信息、端口、重命名</h3> <h4 id="查看容器运行日志"><a href="#查看容器运行日志" class="header-anchor">#</a> 查看容器运行日志</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker logs <span class="token punctuation">[</span>容器id<span class="token punctuation">]</span>
<span class="token comment">#命令效果：</span>
$ docker logs 7c5a24a68f96
</code></pre></div><h4 id="查看容器详细信息"><a href="#查看容器详细信息" class="header-anchor">#</a> 查看容器详细信息</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker inspect <span class="token punctuation">[</span>容器id<span class="token punctuation">]</span>
<span class="token comment">#命令效果：</span>
查看容器全部信息:
$ docker inspect 930f29ccdf8a

</code></pre></div><h4 id="查看容器端口信息"><a href="#查看容器端口信息" class="header-anchor">#</a> 查看容器端口信息</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker port <span class="token punctuation">[</span>容器id<span class="token punctuation">]</span>
<span class="token comment">#命令效果：</span>
$ docker port 930f29ccdf8a
<span class="token comment">#没有效果没有和宿主机关联</span>
</code></pre></div><h4 id="容器重命名"><a href="#容器重命名" class="header-anchor">#</a> 容器重命名</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#作用：</span>
	修改容器的名称
<span class="token comment">#命令格式：</span>
	docker <span class="token function">rename</span> <span class="token punctuation">[</span>容器id<span class="token punctuation">]</span>或<span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span> <span class="token punctuation">[</span>容器新名称<span class="token punctuation">]</span>
<span class="token comment">#命令效果：</span>
$ docker <span class="token function">rename</span> 930f29ccdf8a u1

</code></pre></div><h4 id="总结"><a href="#总结" class="header-anchor">#</a> 总结</h4> <p><img src="assets/rqz2.png" alt="rqz2"></p> <h2 id="_2-3-数据管理"><a href="#_2-3-数据管理" class="header-anchor">#</a> 2.3 数据管理</h2> <p>​	生产环境使用Docker的过程中，往往需要对数据进行持久化保存，或者需要更多容器之间进行数据共享，那我们需要怎么要的操作呢？</p> <p>​	答案就是：数据卷（Data Volumes）和数据卷容器（Data Volume Containers）</p> <h3 id="_2-3-1-数据卷简介"><a href="#_2-3-1-数据卷简介" class="header-anchor">#</a> 2.3.1 数据卷简介</h3> <h4 id="什么是数据卷？"><a href="#什么是数据卷？" class="header-anchor">#</a> 什么是数据卷？</h4> <p>​	就是将宿主机的某个目录，映射到容器中，作为数据存储的目录，我们就可以在宿主机对数据进行存储</p> <p>​	数据卷（Data Volumes）：容器内数据直接映射到本地主机环境</p> <h5 id="数据卷特性"><a href="#数据卷特性" class="header-anchor">#</a> 数据卷特性</h5> <p>1、数据卷可以在容器之间共享和重用，本地与容器间传递数据更高效；</p> <p>2、对数据卷的修改会立马有效，容器内部与本地目录均可；</p> <p>3、对数据卷的更新，不会影响镜像，对数据与应用进行了解耦操作；</p> <p>4、卷会一直存在，直到没有容器使用。</p> <h4 id="docker-数据卷命令详解"><a href="#docker-数据卷命令详解" class="header-anchor">#</a> docker 数据卷命令详解</h4> <div class="language-shell extra-class"><pre class="language-shell"><code>:~$ docker run --help

-v, --volume list               Bind <span class="token function">mount</span> a volume <span class="token punctuation">(</span>default <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
                                    挂载一个数据卷，默认为空
</code></pre></div><p>​	我们可以使用命令 docker run 用来创建容器，可以在使用docker run 命令时添加 -v 参数，就可以创建并挂载一个到多个数据卷到当前运行的容器中。
​	-v 参数的作用是将宿主机的一个目录作为容器的数据卷挂载到docker容器中，使宿主机和容器之间可以共享一个 目录，如果本地路径不存在，Docker也会自动创建。</p> <h3 id="_2-3-2-数据卷实践"><a href="#_2-3-2-数据卷实践" class="header-anchor">#</a> 2.3.2 数据卷实践</h3> <p>​	关于数据卷的管理我们从两个方面来说：</p> <p>1、目录</p> <p>2、普通文件</p> <h4 id="数据卷实践-之-目录"><a href="#数据卷实践-之-目录" class="header-anchor">#</a> 数据卷实践 之 目录</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker run -itd --name <span class="token punctuation">[</span>容器名字<span class="token punctuation">]</span> -v <span class="token punctuation">[</span>宿主机目录<span class="token punctuation">]</span>:<span class="token punctuation">[</span>容器目录<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span> <span class="token punctuation">[</span>命令<span class="token punctuation">(</span>可选<span class="token punctuation">)</span><span class="token punctuation">]</span>

<span class="token comment">#命令演示：</span>
<span class="token comment">#创建测试文件:</span>
$ <span class="token builtin class-name">echo</span> <span class="token string">&quot;file1&quot;</span> <span class="token operator">&gt;</span> tmp/file1.txt
<span class="token comment">#启动一个容器，挂载数据卷:</span>
$ docker run -itd --name test1 -v /home/itcast/tmp/:/test1/  nginx
<span class="token comment">#注意宿主机目录需要绝对路径</span>
<span class="token comment">#测试效果</span>
$ docker <span class="token builtin class-name">exec</span> -it a53c61c77 /bin/bash
root@a53c61c77bde:/<span class="token comment"># cat /test1/file1.txt </span>
file1
</code></pre></div><h4 id="数据卷实践-之-文件-不推荐"><a href="#数据卷实践-之-文件-不推荐" class="header-anchor">#</a> 数据卷实践 之 文件{不推荐}</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker run -itd --name <span class="token punctuation">[</span>容器名字<span class="token punctuation">]</span> -v <span class="token punctuation">[</span>宿主机文件<span class="token punctuation">]</span>:<span class="token punctuation">[</span>容器文件<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span> <span class="token punctuation">[</span>命令<span class="token punctuation">(</span>可选<span class="token punctuation">)</span><span class="token punctuation">]</span>

<span class="token comment">#命令演示：</span>
<span class="token comment">#创建测试文件</span>
$ <span class="token builtin class-name">echo</span> <span class="token string">&quot;file1&quot;</span> <span class="token operator">&gt;</span> /tmp/file1.txt
<span class="token comment">#启动一个容器，挂载数据卷</span>
$ docker run -itd --name test2 -v /home/itcast/tmp/file1.txt:/nihao/nihao.sh nginx
 
<span class="token comment">#测试效果</span>
:~$ docker <span class="token builtin class-name">exec</span> -it 84c37743 /bin/bash
root@84c37743d339:/<span class="token comment"># cat /nihao/nihao.sh </span>
file1
</code></pre></div><h4 id="注意：-2"><a href="#注意：-2" class="header-anchor">#</a> 注意：</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token number">1</span>、Docker挂载数据卷的默认读写权限（rw），用户可以通过ro设置为只读
格式：<span class="token punctuation">[</span>宿主机文件<span class="token punctuation">]</span>:<span class="token punctuation">[</span>容器文件<span class="token punctuation">]</span>:ro
<span class="token number">2</span>、如果直接挂载一个文件到容器，使用文件工具进行编辑，可能会造成文件的改变，从Docker1.1.0起，这会导致报错误信息。所以推荐的方式是直接挂在文件所在的目录。
</code></pre></div><h3 id="_2-3-3-数据卷容器简介"><a href="#_2-3-3-数据卷容器简介" class="header-anchor">#</a> 2.3.3 数据卷容器简介</h3> <p>什么是数据卷容器？
需要在多个容器之间共享一些持续更新的数据，最简单的方式是使用数据卷容器。数据卷容器也是一个容器，但是它的目的是专门用来提供数据卷供其他容器挂载。</p> <p>数据卷容器（Data Volume Containers）：使用特定容器维护数据卷</p> <p>简单点：数据卷容器就是为其他容器提供数据交互存储的容器</p> <h4 id="docker-数据卷命令详解-2"><a href="#docker-数据卷命令详解-2" class="header-anchor">#</a> docker 数据卷命令详解</h4> <div class="language-shell extra-class"><pre class="language-shell"><code>:~$  docker run --help
。。。
-v, --volumes-from list     Mount volumes from the specified container<span class="token punctuation">(</span>s<span class="token punctuation">)</span> <span class="token punctuation">(</span>default<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
                                  <span class="token comment">#从指定的容器挂载卷，默认为空</span>
</code></pre></div><h4 id="数据卷容器操作流程"><a href="#数据卷容器操作流程" class="header-anchor">#</a> 数据卷容器操作流程</h4> <p>如果使用数据卷容器，在多个容器间共享数据，并永久保存这些数据，需要有一个规范的流程才能做得到：</p> <p>1、创建数据卷容器</p> <p>2、其他容器挂载数据卷容器</p> <p>注意：
数据卷容器自身并不需要启动，但是启动的时候依然可以进行数据卷容器的工作。</p> <h3 id="_2-3-4-数据卷容器实践"><a href="#_2-3-4-数据卷容器实践" class="header-anchor">#</a> 2.3.4 数据卷容器实践</h3> <p>数据卷容器实践包括两部分：创建数据卷容器和使用数据卷容器</p> <h4 id="创建一个数据卷容器"><a href="#创建一个数据卷容器" class="header-anchor">#</a> 创建一个数据卷容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker create -v <span class="token punctuation">[</span>容器数据卷目录<span class="token punctuation">]</span> --name <span class="token punctuation">[</span>容器名字<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span> <span class="token punctuation">[</span>命令<span class="token punctuation">(</span>可选<span class="token punctuation">)</span><span class="token punctuation">]</span>
<span class="token comment">#执行效果</span>
$ docker create -v /data --name v1-test1 nginx
</code></pre></div><h4 id="创建两个容器，同时挂载数据卷容器"><a href="#创建两个容器，同时挂载数据卷容器" class="header-anchor">#</a> 创建两个容器，同时挂载数据卷容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker run --volumes-from <span class="token punctuation">[</span>数据卷容器id/name<span class="token punctuation">]</span> -tid --name <span class="token punctuation">[</span>容器名字<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span> <span class="token punctuation">[</span>命令<span class="token punctuation">(</span>可选<span class="token punctuation">)</span><span class="token punctuation">]</span>
<span class="token comment">#执行效果：</span>
<span class="token comment">#创建 vc-test1 容器:</span>
docker run --volumes-from 4693558c49e8 -tid --name vc-test1 nginx /bin/bash
<span class="token comment">#创建 vc-test2 容器:</span>
docker run --volumes-from 4693558c49e8 -tid --name vc-test2 nginx /bin/bash

</code></pre></div><h4 id="确认卷容器共享"><a href="#确认卷容器共享" class="header-anchor">#</a> 确认卷容器共享</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#进入vc-test1，操作数据卷容器:</span>
:~$  docker <span class="token builtin class-name">exec</span> -it vc-test1 /bin/bash
root@c408f4f14786:/<span class="token comment"># ls /data/</span>
root@c408f4f14786:/<span class="token comment"># echo 'v-test1' &gt; /data/v-test1.txt</span>
root@c408f4f14786:/<span class="token comment"># exit</span>
<span class="token comment">#进入vc-test2，确认数据卷:</span>
:~$  docker <span class="token builtin class-name">exec</span> -it vc-test2 /bin/bash
root@7448eee82ab0:/<span class="token comment"># echo 'v-test2' &gt; /data/v-test2.txt</span>
root@7448eee82ab0:/<span class="token comment"># ls /data/</span>
v-test1.txt
root@7448eee82ab0:/<span class="token comment"># exit</span>
<span class="token comment">#回到vc-test1进行验证</span>
:~$  docker <span class="token builtin class-name">exec</span> -it vc-test1 /bin/bash
root@c408f4f14786:/<span class="token comment"># ls /data/</span>
v-test1.txt  v-test2.txt
root@c408f4f14786:/<span class="token comment"># cat /data/v-test2.txt </span>
v-test2
</code></pre></div><h3 id="_2-3-5-数据备份原理"><a href="#_2-3-5-数据备份原理" class="header-anchor">#</a> 2.3.5 数据备份原理</h3> <p>为什么需要数据备份和恢复？
工作中很多的容器的数据需要查看，所有需要备份将数据很轻松的拿到本地目录。</p> <p>原理图：</p> <p><img src="assets/%E5%A4%87%E4%BB%BD.png" alt="备份"></p> <p>数据备份方案：
1 创建一个挂载数据卷容器的容器</p> <p>2 挂载宿主机本地目录作为备份数据卷</p> <p>3 将数据卷容器的内容备份到宿主机本地目录挂载的数据卷中</p> <p>4 完成备份操作后销毁刚创建的容器</p> <h3 id="_2-3-6-数据备份实践"><a href="#_2-3-6-数据备份实践" class="header-anchor">#</a> 2.3.6 数据备份实践</h3> <p>在2.3.4的数据卷容器基础上做数据的备份</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
$ docker run --rm --volumes-from <span class="token punctuation">[</span>数据卷容器id/name<span class="token punctuation">]</span> -v <span class="token punctuation">[</span>宿主机目录<span class="token punctuation">]</span>:<span class="token punctuation">[</span>容器目录<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span> <span class="token punctuation">[</span>备份命令<span class="token punctuation">]</span>

<span class="token comment">#命令演示：</span>
<span class="token comment">#创建备份目录:</span>
$ <span class="token function">mkdir</span> /backup/
<span class="token comment">#创建备份的容器:</span>
$ docker run --rm --volumes-from 60205766d61a  -v /home/itcast/backup/:/backup/ nginx <span class="token function">tar</span> zcPf /backup/data.tar.gz /data

<span class="token comment">#验证操作:</span>
$ <span class="token function">ls</span> /backup
$ zcat /backup/data.tar.gz
</code></pre></div><p>注释:
​	-P：使用原文件的原来属性（属性不会依据使用者而变），恢复字段到它们的原始方式，忽略现有的用户权限屏蔽位（umask)。 加了-p之后，tar进行解压后，生成的文件的权限，是直接取自tar包里面文件的权限（不会再使用该用户的umask值进行运算），那么不加-p参数，将还要再减去umask的值（位运算的减），但是如果使用root用户进行操作，加不加-p参数都一样。</p> <h3 id="_2-3-7-数据还原原理"><a href="#_2-3-7-数据还原原理" class="header-anchor">#</a> 2.3.7 数据还原原理</h3> <p>原理图：</p> <p>数据恢复方案<img src="assets/%E8%BF%98%E5%8E%9F.png" alt="还原">
1、创建一个新的数据卷容器（或删除原数据卷容器的内容）</p> <p>2、创建一个新容器，挂载数据卷容器，同时挂载本地的备份目录作为数据卷</p> <p>3、将要恢复的数据解压到容器中</p> <p>4、完成还原操作后销毁刚创建的容器</p> <h3 id="_2-3-8-数据还原实践"><a href="#_2-3-8-数据还原实践" class="header-anchor">#</a> 2.3.8 数据还原实践</h3> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker run --rm -itd --volumes-from <span class="token punctuation">[</span>数据要到恢复的容器<span class="token punctuation">]</span> -v <span class="token punctuation">[</span>宿主机备份目录<span class="token punctuation">]</span>:<span class="token punctuation">[</span>容器备份目录<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>  <span class="token punctuation">[</span>解压命令<span class="token punctuation">]</span>
<span class="token comment">#命令实践：</span>
<span class="token comment">#启动数据卷容器:</span>
$ docker start c408f4f14786

<span class="token comment">#删除源容器内容:</span>
$  docker <span class="token builtin class-name">exec</span> -it vc-test1 <span class="token function">bash</span> 
root@c408f4f14786:/<span class="token comment"># rm -rf /data/*</span>

<span class="token comment">#恢复数据:</span>
docker run --rm --volumes-from v-test  -v /home/itcast/backup/:/backup/ nginx <span class="token function">tar</span> xPf /backup/data.tar.gz -C /data

<span class="token comment">#验证:</span>
:~$ docker <span class="token builtin class-name">exec</span> -it vc-test1/bin/bash 
root@c408f4f14786:/<span class="token comment"># ls /data/data/</span>
v-test1.txt  v-test2.txt
 
<span class="token comment">#新建新的数据卷容器：</span>
:~$ docker create -v /newdata --name v-test2 nginx
<span class="token comment">#简历新的容器挂载数据卷容器</span>
:~$ docker run --volumes-from a7e9a33f3acb -tid --name vc-test3 nginx /bin/bash
<span class="token comment">#恢复数据：</span>
docker run --rm --volumes-from v-test2  -v /home/itcast/backup/:/backup/ nginx <span class="token function">tar</span> xPf /backup/data.tar.gz -C /newdata
<span class="token comment">#验证:</span>
:~$ docker <span class="token builtin class-name">exec</span> -it vc-test3 /bin/bash 
root@c408f4f14786:/<span class="token comment"># ls /newdata</span>
v-test1.txt  v-test2.txt
</code></pre></div><p>注意：
解压的时候，如果使用目录的话，一定要在解压的时候使用 -C 制定挂载的数据卷容器，不然的话容器数据是无法恢复的，因为容器中默认的backup目录不是数据卷，即使解压后，也看不到文件。</p> <p>数据是最宝贵的资源，docker在设计上考虑到了这点，并且为数据的操作提供了充分的支持。</p> <h2 id="_2-4-网络管理"><a href="#_2-4-网络管理" class="header-anchor">#</a> 2.4 网络管理</h2> <p>​	Docker 网络很重要，重要的，我们在上面学到的所有东西都依赖于网络才能工作。我们从两个方面来学习网络：端口映射和网络模式
​	为什么先学端口映射呢？
在一台主机上学习网络，学习端口映射最简单，避免过多干扰。</p> <h3 id="_2-4-1-端口映射详解"><a href="#_2-4-1-端口映射详解" class="header-anchor">#</a> 2.4.1 端口映射详解</h3> <p>默认情况下，容器和宿主机之间网络是隔离的，我们可以通过端口映射的方式，将容器中的端口，映射到宿主机的某个端口上。这样我们就可以通过宿主机的ip+port的方式来访问容器里的内容</p> <p><strong>Docker的端口映射</strong></p> <p>1、随机映射     -P(大写)</p> <p>2、指定映射     -p 宿主机ip:宿主机端口:容器端口</p> <p>注意：
生产场景一般不使用随机映射，但是随机映射的好处就是由docker分配，端口不会冲突,
不管哪种映射都会有所消耗，影响性能，因为涉及到映射的操作</p> <h3 id="_2-4-2-随机映射实践"><a href="#_2-4-2-随机映射实践" class="header-anchor">#</a> 2.4.2 随机映射实践</h3> <p>随机映射我们从两个方面来学习：
1、默认随机映射
2、指定主机随机映射</p> <h4 id="默认随机映射"><a href="#默认随机映射" class="header-anchor">#</a> 默认随机映射</h4> <div class="language-SHELL extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker run -d -P <span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>
<span class="token comment">#命令效果：</span>
<span class="token comment">#先启动一个普通的nginx镜像</span>
$ docker run -d  nginx
<span class="token comment">#查看当前宿主机开放了哪些端口</span>
$ <span class="token function">netstat</span> -tnulp
</code></pre></div><p><img src="assets/clip_image002.jpg" alt="Proto  tcp  o.o.o.o:22  tcp  tcp  tcp6  tcp6  udp  udp  udp  udp  udp  udp6  udp6  Recv-Q  Send-Q  Local  Address  Foreign  o.o.o  o.o.o  o.o.o  o.o.o  o.o.o  o.o.o  o.o.o  o.o.o  Address  State  LISTEN  LISTEN  LISTEN  LISTEN  LISTEN  PID/Program name  127.0.1.1:53  127.0.0.1:631  o.o.o.o:5353  o.o.o.o:38319  o.o.o.o:48822  127.0. 1.1 53  o.o.o.o:55919  o ..:33152 "></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#启动一个默认随机映射的nginx镜像</span>
$ docker run -d -P nginx
<span class="token comment">#查看当前宿主机开放了哪些端口</span>
$ <span class="token function">netstat</span> -tnulp
</code></pre></div><p><img src="assets/clip_image002-1538459623213.jpg" alt="N31S11  N31S11  N31S11  N31S11  N31S11  N31S11  aweu we-150-1d/OId  ssauppv  ZSIEE  ESES.  ES:VVYLZI  89LZE...  189. I..  ES:VVYLZI  ssauppv  leoo-l  D-puas  9dpn  9dpn  dpn  dpn  dpn  dpn  dpn  9dm  dm  dm  dm  modd "></p> <p><img src="assets/clip_image004.jpg" alt="docker  CONTAINER ID  564843c57f56  of...&quot;  -g  1b8875c344fe  of...&quot;  -g  itcast@itcast-virtual-machine : —$  IMAGE  nglnx  nglnx  ps  COMMAND  &quot; nglnx  &quot; nglnx  daemon  daemon  CREATED  6 minutes  6 minutes  ago  ago  STATUS  Up 6 minutes  Up 6 minutes  PORTS  o.o.o.o:32768  80/tcp  -&gt;80/tcp  NAMES  modest swartz  zealous jackson "></p> <p><strong>注意：</strong>
​    宿主机的32768被映射到容器的80端口
-P 自动绑定所有对外提供服务的容器端口，映射的端口将会从没有使用的端口池中自动随机选择，
但是如果连续启动多个容器的话，则下一个容器的端口默认是当前容器占用端口号+1</p> <p><img src="assets/1541588399807.png" alt="1541588399807"></p> <p>在浏览器中访问http://192.168.110.20:32768</p> <p>效果显示
<img src="assets/1541588444804.png" alt="1541588444804"></p> <p>注意：
浏览器输入的格式是： docker容器宿主机的ip:容器映射的端口</p> <h4 id="指定主机随机映射"><a href="#指定主机随机映射" class="header-anchor">#</a> 指定主机随机映射</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式</span>
    :~$ docker run -d -p <span class="token punctuation">[</span>宿主机ip<span class="token punctuation">]</span>::<span class="token punctuation">[</span>容器端口<span class="token punctuation">]</span> --name <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>
<span class="token comment">#命令效果</span>
    :~$ docker run -d -p <span class="token number">192.168</span>.8.14::80 --name nginx-1 nginx
<span class="token comment">#检查效果</span>
    :~$ docker <span class="token function">ps</span> 
</code></pre></div><h3 id="_2-4-3-指定映射实践"><a href="#_2-4-3-指定映射实践" class="header-anchor">#</a> 2.4.3 指定映射实践</h3> <p><strong>指定端口映射我们从二个方面来讲</strong>：</p> <p>指定端口映射</p> <p>指定多端口映射</p> <h4 id="指定端口映射"><a href="#指定端口映射" class="header-anchor">#</a> 指定端口映射</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
    docker run -d -p <span class="token punctuation">[</span>宿主机ip<span class="token punctuation">]</span>:<span class="token punctuation">[</span>宿主机端口<span class="token punctuation">]</span>:<span class="token punctuation">[</span>容器端口<span class="token punctuation">]</span> --name <span class="token punctuation">[</span>容器名字<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>
<span class="token comment">#注意：</span>
<span class="token comment">#如果不指定宿主机ip的话，默认使用 0.0.0.0，</span>
    
<span class="token comment">#命令实践：</span>
<span class="token comment">#现状我们在启动容器的时候，给容器指定一个访问的端口 1199</span>
    docker run -d -p <span class="token number">192.168</span>.8.14:1199:80 --name nginx-2 nginx
<span class="token comment">#查看新容器ip</span>
    docker inspect --format<span class="token operator">=</span><span class="token string">'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'</span> 0ad3acfbfb76
<span class="token comment">#查看容器端口映射</span>
    docker <span class="token function">ps</span> 
</code></pre></div><h4 id="多端口映射方法"><a href="#多端口映射方法" class="header-anchor">#</a> 多端口映射方法</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式</span>
    docker run -d -p <span class="token punctuation">[</span>宿主机端口1<span class="token punctuation">]</span>:<span class="token punctuation">[</span>容器端口1<span class="token punctuation">]</span>  -p <span class="token punctuation">[</span>宿主机端口2<span class="token punctuation">]</span>:<span class="token punctuation">[</span>容器端口2<span class="token punctuation">]</span> --name <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span> 
<span class="token comment">#开起多端口映射实践</span>
    docker run -d -p <span class="token number">520</span>:443 -p <span class="token number">6666</span>:80 --name nginx-3 nginx
<span class="token comment">#查看容器进程</span>
    docker <span class="token function">ps</span> 
</code></pre></div><h3 id="_2-4-4-网络管理基础"><a href="#_2-4-4-网络管理基础" class="header-anchor">#</a> 2.4.4 网络管理基础</h3> <h4 id="docker网络命令"><a href="#docker网络命令" class="header-anchor">#</a> docker网络命令</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#查看网络命令帮助</span>
:~$ docker network <span class="token builtin class-name">help</span>
    。。。。。。
connect     Connect a container to a network
   <span class="token comment">#将一个容器连接到一个网络</span>
create      Create a network
   <span class="token comment">#创建一个网络</span>
disconnect  Disconnect a container from a network
   <span class="token comment">#从网络断开一个容器</span>
inspect     Display detailed information on one or <span class="token function">more</span> networks
   <span class="token comment">#在一个或多个网络上显示详细信息</span>
<span class="token function">ls</span>          List networks
   <span class="token comment">#网络列表</span>
prune       Remove all unused networks
   <span class="token comment">#删除所有未使用的网络</span>
<span class="token function">rm</span>          Remove one or <span class="token function">more</span> networks
   <span class="token comment">#删除一个或多个网络。</span>
</code></pre></div><h4 id="经常使用的网络查看命令"><a href="#经常使用的网络查看命令" class="header-anchor">#</a> 经常使用的网络查看命令</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#查看当前主机网络</span>
$ docker network <span class="token function">ls</span>

NETWORK ID          NAME                DRIVER              SCOPE
<span class="token comment">#网络id             #名称               #驱动                #范围</span>
c2dcffa83a29        bridge              bridge              <span class="token builtin class-name">local</span>
c4deefdaf53b        <span class="token function">host</span>                <span class="token function">host</span>                <span class="token builtin class-name">local</span>
57942890c6d6        none                null                <span class="token builtin class-name">local</span>
</code></pre></div><div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#查看bridge的网络内部信息</span>
:~$ docker network inspect bridge
<span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
        <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;bridge&quot;</span>,
。。。。。。
            <span class="token string">&quot;Config&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
                <span class="token punctuation">{</span>
                    <span class="token string">&quot;Subnet&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.17.0.0/16&quot;</span>,
                    <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.17.0.1&quot;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">]</span>
        <span class="token punctuation">}</span>,
。。。。。。
        <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
            <span class="token string">&quot;1f182f7163cb194c7d49c75e46fc6dc7cbee59b55f04d74319df75b45a6f5ba0&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx-2&quot;</span>,
                <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;9e91f5d77b9c0ef85bb8a4f8aa2f4fb883243371b0946ee5f5e728ba9a409b0d&quot;</span>,
                <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;02:42:ac:11:00:03&quot;</span>,
                <span class="token string">&quot;IPv4Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.17.0.3/16&quot;</span>,
                <span class="token string">&quot;IPv6Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>
            <span class="token punctuation">}</span>,
            <span class="token string">&quot;faecdcae982a658b1c1a1abbd57125ca5eae5234d3e684ce771b8a952317a3b6&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx-1&quot;</span>,
                <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;72f7a99c28838ee670240c9e7bd79eee24c0dea28203e4fe0286fdb3ab084ac7&quot;</span>,
                <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;02:42:ac:11:00:02&quot;</span>,
                <span class="token string">&quot;IPv4Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.17.0.2/16&quot;</span>,
                <span class="token string">&quot;IPv6Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>,
      <span class="token punctuation">]</span>
</code></pre></div><h4 id="回忆一下"><a href="#回忆一下" class="header-anchor">#</a> <strong>回忆一下</strong></h4> <h5 id="查看容器详细信息-2"><a href="#查看容器详细信息-2" class="header-anchor">#</a> 查看容器详细信息</h5> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
    docker inspect <span class="token punctuation">[</span>容器id<span class="token punctuation">]</span>
<span class="token comment">#命令效果：</span>
    查看容器全部信息:
    :~$ docker inspect 930f29ccdf8a
    查看容器网络信息:
    :~$ docker inspect --format<span class="token operator">=</span><span class="token string">'{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'</span> 930f29ccdf8a
</code></pre></div><h5 id="查看容器端口信息-2"><a href="#查看容器端口信息-2" class="header-anchor">#</a> 查看容器端口信息</h5> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
    docker port <span class="token punctuation">[</span>容器id<span class="token punctuation">]</span>
<span class="token comment">#命令效果：</span>
    :~$ docker port 930f29ccdf8a
</code></pre></div><h3 id="_2-4-5-网络模式简介"><a href="#_2-4-5-网络模式简介" class="header-anchor">#</a> 2.4.5 网络模式简介</h3> <p>​	从1.7.0版本开始，Docker正式把网络跟存储这两个部分的功能实现都以插件化的形式剥离出来，允许用户通过指令来选择不同的后端实现。这也就是Docker希望构建围绕着容器的强大生态系统的一些积极尝试。
​	剥离出来的独立网络项目叫做libnetwork，libnetwork中的网络模型（Container Networking Model ，CNM）十分简洁，可以让上层的大量应用容器最大程度上不去关心底层实现。</p> <h4 id="docker的常用的网络模式"><a href="#docker的常用的网络模式" class="header-anchor">#</a> docker的常用的网络模式</h4> <p><strong>bridge模式：</strong>
简单来说：就是穿马甲，打着宿主机的旗号，做自己的事情。
Docker的<strong>默认模式</strong>，它会在docker容器启动时候，自动配置好自己的网络信息，同一宿主机的所有容器都在一个网络下，彼此间可以通信。类似于我们vmware虚拟机的桥接模式。
利用宿主机的网卡进行通信，因为涉及到网络转换，所以会造成资源消耗，网络效率会低。</p> <p><img src="assets/1541589586675.png" alt="1541589586675"></p> <p><strong>host模式：</strong>
简单来说，就是鸠占鹊巢，用着宿主机的东西，干自己的事情。容器使用宿主机的ip地址进行通信。
特点：容器和宿主机共享网络</p> <p><img src="assets/1541589598705.png" alt="1541589598705"></p> <p><strong>container模式：</strong>
新创建的容器间使用，使用已创建的容器网络，类似一个局域网。
特点：容器和容器共享网络</p> <p><img src="assets/1541589611351.png" alt="1541589611351"></p> <p><strong>none模式：</strong>
这种模式最纯粹，不会帮你做任何网络的配置，可以最大限度的定制化。
不提供网络服务，容器启动后无网络连接。</p> <p><img src="assets/1541589645492.png" alt="1541589645492"></p> <p><strong>overlay模式：</strong>
容器彼此不再同一网络，而且能互相通行。</p> <p><img src="assets/1541589665251.png" alt="1541589665251"></p> <h3 id="_2-4-6-定制bridge实践一"><a href="#_2-4-6-定制bridge实践一" class="header-anchor">#</a> 2.4.6 定制bridge实践一</h3> <p>​	其实我们在端口映射的部分就是bridge模式的简单演示了，因为他们使用的是默认bridge网络模式，现在我们来自定义桥接网络。
​	<strong>这一部分我们从三个方面来演示：</strong>
​	创建桥接网络</p> <p>​	使用自定义网络创建容器</p> <p>​	容器断开、连接网络</p> <h4 id="创建网络"><a href="#创建网络" class="header-anchor">#</a> 创建网络</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
docker network create --driver <span class="token punctuation">[</span>网络类型<span class="token punctuation">]</span><span class="token punctuation">[</span>网络名称<span class="token punctuation">]</span>

<span class="token comment">#参数</span>
create  	创建一个网络
--driver	指定网络类型

<span class="token comment">#命令演示：</span>
$ docker network create --driver bridge bridge-test

<span class="token comment">#查看主机网络类型:</span>
:~$ docker network <span class="token function">ls</span>
NETWORK ID          NAME                DRIVER              SCOPE
<span class="token comment">#网络id              #名称               #驱动                #范围</span>
c2dcffa83a29        bridge              bridge              <span class="token builtin class-name">local</span>
c4deefdaf53b        <span class="token function">host</span>                <span class="token function">host</span>                <span class="token builtin class-name">local</span>
57942890c6d6        none                null                <span class="token builtin class-name">local</span>
d5c061bc02b1        bridge-test         bridge              <span class="token builtin class-name">local</span> 

<span class="token comment">#查看新建网络的网络信息</span>
:~$ docker network inspect  bridge-test 
<span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
        <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;bridge-test&quot;</span>,
。。。。。。
            <span class="token string">&quot;Config&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
                <span class="token punctuation">{</span>
                    <span class="token string">&quot;Subnet&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.18.0.0/16&quot;</span>,<span class="token comment">#ip/子网</span>
                    <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.18.0.1&quot;</span>#网关
                <span class="token punctuation">}</span>
            <span class="token punctuation">]</span>
        <span class="token punctuation">}</span>,
。。。。。。
    <span class="token punctuation">}</span>
<span class="token punctuation">]</span>

<span class="token comment">#宿主机又多出来一个网卡设备：</span>
$ <span class="token function">ifconfig</span>
br-17847710137f Link encap:以太网  硬件地址 02:42:cb:8b:48:37  
inet 地址:172.18.0.1  广播:172.18.255.255  掩码:255.255.0.0
。。。。。。
</code></pre></div><h4 id="自定义网段与网关"><a href="#自定义网段与网关" class="header-anchor">#</a> 自定义网段与网关</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#自定义网段与网关</span>
<span class="token comment">#查看关于网段和网管的相关命令</span>
:~$ docker network create --help

--gateway strings      IPv4 or IPv6 Gateway <span class="token keyword">for</span> the master subnet
                           主子网的IPv4或IPv6网关。

--subnet strings       Subnet <span class="token keyword">in</span> CIDR <span class="token function">format</span> that represents a network segment
                        表示网络段的CIDR格式的子网。
<span class="token comment">#查看刚刚创建的网络信息</span>
:~$ docker network inspect bridge-test 
<span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
        <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;bridge-test&quot;</span>,

。。。
        <span class="token string">&quot;Config&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
                <span class="token string">&quot;Subnet&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.18.0.0/16&quot;</span>,<span class="token comment">#ip/子网</span>
                <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.18.0.1&quot;</span>#网关
。。。

<span class="token comment">#创建自定义网段与网关信息</span>
:~$ docker network create --driver bridge --gateway <span class="token number">172.99</span>.0.1 --subnet <span class="token number">172.99</span>.0.0/16 bridge-test1
<span class="token comment">#成功返回对应的sha256码</span>
9d02a01fa98b7a538027b624171481a2098232fa707cdc83084fc880d0afd091

<span class="token comment">#查看网络列表</span>
:~$ docker network <span class="token function">ls</span>
NETWORK ID          NAME                DRIVER              SCOPE
c2dcffa83a29        bridge              bridge              <span class="token builtin class-name">local</span>
17847710137f        bridge-test         bridge              <span class="token builtin class-name">local</span>
9d02a01fa98b        bridge-test1        bridge              <span class="token builtin class-name">local</span>
c4deefdaf53b        <span class="token function">host</span>                <span class="token function">host</span>                <span class="token builtin class-name">local</span>
57942890c6d6        none                null                <span class="token builtin class-name">local</span>

<span class="token comment">#查看自定义网络的网关与网络信息</span>
:~$ docker network inspect bridge-test1 
<span class="token punctuation">[</span>
    <span class="token punctuation">{</span>
            <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;bridge-test1&quot;</span>,
。。。。。。
            <span class="token string">&quot;Config&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
                <span class="token punctuation">{</span>
                    <span class="token string">&quot;Subnet&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.99.0.0/16&quot;</span>#ip/子网
                    <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.99.0.1&quot;</span>#网关
                <span class="token punctuation">}</span>
。。。。
<span class="token comment">#查看主机网络信息</span>
$ <span class="token function">ifconfig</span>
br-9d02a01fa98b Link encap:以太网  硬件地址 02:42:41:18:2c:5a  
          inet 地址:172.99.0.1  广播:172.99.255.255  掩码:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  跃点数:1
          接收数据包:0 错误:0 丢弃:0 过载:0 帧数:0
          发送数据包:0 错误:0 丢弃:0 过载:0 载波:0
          碰撞:0 发送队列长度:0 
          接收字节:0 <span class="token punctuation">(</span><span class="token number">0.0</span> B<span class="token punctuation">)</span>  发送字节:0 <span class="token punctuation">(</span><span class="token number">0.0</span> B<span class="token punctuation">)</span>
</code></pre></div><h4 id="在自定义网络中启动容器"><a href="#在自定义网络中启动容器" class="header-anchor">#</a> 在自定义网络中启动容器</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式： </span>
    docker run --net<span class="token operator">=</span><span class="token punctuation">[</span>网络名称<span class="token punctuation">]</span> -itd --name<span class="token operator">=</span><span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span><span class="token punctuation">[</span>镜像名称<span class="token punctuation">]</span>
<span class="token comment">#使用效果：</span>
    <span class="token comment">#查看创建的网络bridge-test</span>
    :~$ docker network inspect bridge-test
            <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>,<span class="token comment">#容器是空的</span>
    <span class="token comment">#查看创建的网络bridge-test1</span>
    :~$ docker network inspect bridge-test1
            <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>,<span class="token comment">#容器也是是空的</span>
    <span class="token comment">#创建启动1个使用网络为bridge-test  名为nginx--1的容器</span>
    :~$ docker run --net<span class="token operator">=</span>bridge-test -itd --name nginx--1 nginx
    ff07009ba3c29872145630814d163ccffe72643abef3acda2d443d6848004d87

``<span class="token variable"><span class="token variable">`</span>
<span class="token comment">#查看下容器</span>
:~$ docker <span class="token function">ps</span>
CONTAINER ID        IMAGE        COMMAND                  CREATED         STATUS          PORTS      NAMES
ff07009ba3c2        nginx        <span class="token string">&quot;nginx -g 'daemon of…&quot;</span>   <span class="token number">2</span> minutes ago   Up <span class="token number">2</span> minutes    <span class="token number">80</span>/tcp     nginx--1
 
<span class="token comment">#查看容器的信息 </span>
:~$ docker inspect ff07009ba3c2
<span class="token comment">#网络信息已经变成bridge-test的网段了</span>
                    <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.18.0.1&quot;</span>,
                    <span class="token string">&quot;IPAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.18.0.2&quot;</span>,
<span class="token comment">#创建启动1个使用网络为bridge-test1  名为nginx--2的容器</span>
:~$ docker run --net<span class="token operator">=</span>bridge-test1 -itd --name nginx--2 nginx
cc55de5710ad8133991d52482d363b42dcdf6fff50f476b3024c626eb1c14da3
 
<span class="token comment">#查看下容器</span>
:~$ docker <span class="token function">ps</span>
CONTAINER ID        IMAGE        COMMAND                  CREATED         STATUS          PORTS      NAMES
cc55de5710ad        nginx        <span class="token string">&quot;nginx -g 'daemon of…&quot;</span>   <span class="token number">5</span> seconds ago   Up <span class="token number">4</span> seconds    <span class="token number">80</span>/tcp     nginx--2
<span class="token comment">#查看容器的信息</span>
:~$ docker inspect cc55de5710ad
<span class="token comment">#网络信息已经变成bridge-test1的网段了</span>
                    <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.99.0.1&quot;</span>,
                    <span class="token string">&quot;IPAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.99.0.2&quot;</span>,

<span class="token comment">#查看bridge-test的网络信息</span>
:~$ docker network inspect bridge-test
<span class="token comment">#bridge-test下包含了nginx--1</span>
        <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
            <span class="token string">&quot;ff07009ba3c29872145630814d163ccffe72643abef3acda2d443d6848004d87&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx--1&quot;</span>,
                <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;e2e8ba3091b27b333cf73673059dbc3a973540873fe64bd6c6300c89dc57eb75&quot;</span>,
                <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;02:42:ac:12:00:02&quot;</span>,
                <span class="token string">&quot;IPv4Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.18.0.2/16&quot;</span>,

<span class="token comment">#查看bridge-test1的网络信息</span>
:~$ docker network inspect bridge-test1
<span class="token comment">#bridge-test下包含了nginx--2</span>
        <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
            <span class="token string">&quot;cc55de5710ad8133991d52482d363b42dcdf6fff50f476b3024c626eb1c14da3&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx--2&quot;</span>,
                <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;66eefc70755e94a306a7b71ea08f262ea656f7e7a2b117ee716e9de2014a35e5&quot;</span>,
                <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;02:42:ac:63:00:02&quot;</span>,
                <span class="token string">&quot;IPv4Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.99.0.2/16&quot;</span>,

<span class="token variable">`</span></span>``

<span class="token comment">#注意部分</span>
<span class="token comment">#使用默认的桥接模型创建的容器是可以直接联网的。</span>
<span class="token comment">#使用自定义的桥接模型创建的容器不可以直接联网，但是可以通过端口映射来实现联网</span>
</code></pre></div><h4 id="容器断开网络"><a href="#容器断开网络" class="header-anchor">#</a> 容器断开网络</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式： </span>
    docker network disconnect <span class="token punctuation">[</span>网络名<span class="token punctuation">]</span><span class="token punctuation">[</span>容器名<span class="token punctuation">]</span> 
<span class="token comment">#命令演示：</span>
    docker network disconnect bridge-test nginx1
<span class="token comment">#效果展示：</span>
    <span class="token comment">#断开容器nginx--1网络bridge-test</span>
    :~$ docker network disconnect bridge-test nginx--1
    
    <span class="token comment">#查看下容器</span>
    :~$ docker <span class="token function">ps</span>
    <span class="token comment">#发现nginx-1的网络消失</span>
    CONTAINER ID        IMAGE        COMMAND                  CREATED             STATUS              PORTS   NAMES
    ff07009ba3c2        nginx        <span class="token string">&quot;nginx -g 'daemon of…&quot;</span>   <span class="token number">37</span> minutes ago      Up <span class="token number">37</span> minutes               nginx--1
    
    <span class="token comment">#断开容器nginx--2网络bridge-test1</span>
    :~$ docker network disconnect bridge-test1 nginx--2 
    
    <span class="token comment">#查看下容器</span>
    :~$ docker <span class="token function">ps</span>
    <span class="token comment">#发现nginx-2的网络消失</span>
    CONTAINER ID        IMAGE        COMMAND                  CREATED             STATUS              PORTS   NAMES
    cc55de5710ad        nginx        <span class="token string">&quot;nginx -g 'daemon of…&quot;</span>   <span class="token number">28</span> minutes ago      Up <span class="token number">28</span> minutes               nginx--2
    
    <span class="token comment">#分别查看网络bridge-test  bridge-test1的网络</span>
    :~$ docker network inspect bridge-test
    :~$ docker network inspect bridge-test1
    <span class="token comment">#发现容器内容消失</span>
            <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>,<span class="token comment">#已经没有容器了</span>
    
    <span class="token comment">#分别查看两个容器的信息发现容器网络信息消失</span>
    :~<span class="token variable">$docker</span> inspect nginx--1
    :~<span class="token variable">$docker</span> inspect nginx--2

 
</code></pre></div><h4 id="容器连接网络"><a href="#容器连接网络" class="header-anchor">#</a> 容器连接网络</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式： </span>
    docker network connect <span class="token punctuation">[</span>网络名<span class="token punctuation">]</span><span class="token punctuation">[</span>容器名<span class="token punctuation">]</span>
<span class="token comment">#命令演示：</span>
<span class="token comment">#将容器nginx--1连接到bridge-test1网络</span>
:~$ docker network connect bridge-test1 nginx--1
:~$ docker <span class="token function">ps</span>
CONTAINERID IMAGE COMMAND             CREATED        STATUS     PORTS NAMES
cc55de5710ad nginx <span class="token string">&quot;nginx-g'daemonof…&quot;</span> Aboutanhourago UpAboutanhour    nginx--2
    
<span class="token comment">#将容器nginx--2连接到bridge-test网络</span>
:~$ docker network connect bridge-test nginx--2
:~$ docker <span class="token function">ps</span>
CONTAINERID  IMAGE COMMAND             CREATED         STATUS        PORTS    NAMES
ff07009ba3c2 nginx <span class="token string">&quot;nginx-g'daemonof…&quot;</span> Aboutanhourago  UpAboutanhour <span class="token number">80</span>/tcp   nginx1
    
查看bridge-test网络是否包含容器
:~$ docker network inspect bridge-test
           <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;cc55de5710ad8133991d52482d363b42dcdf6fff50f476b3024c626eb1c14da3&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                    <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx--2&quot;</span>,
                    <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;6eee4258bc62645fd611f292f52e8b0ea2d0262ab5c99bc097f26eed95d1f886&quot;</span>,
                    <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;02:42:ac:12:00:02&quot;</span>,
                    <span class="token string">&quot;IPv4Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.18.0.2/16&quot;</span>,
                    <span class="token string">&quot;IPv6Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>
                    
查看bridge-test1网络是否包含容器
:~$ docker network inspect bridge-test1
            <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;ff07009ba3c29872145630814d163ccffe72643abef3acda2d443d6848004d87&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                    <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx--1&quot;</span>,
                    <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;0c0367f49338274698e58aed371bf582d931d5824edf7f1385637ea3fabd242c&quot;</span>,
                    <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;02:42:ac:63:00:02&quot;</span>,
                    <span class="token string">&quot;IPv4Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;172.99.0.2/16&quot;</span>,
                    <span class="token string">&quot;IPv6Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>
</code></pre></div><h3 id="_2-4-7-定制bridge实践二"><a href="#_2-4-7-定制bridge实践二" class="header-anchor">#</a> 2.4.7 定制bridge实践二</h3> <p>​	之前我们创建的容器，它们的ip都是从docker0自动获取的，接下来我们自己定义一个br0网桥，然后启动的容器就用这个</p> <p><strong>网桥是什么？</strong>
他是一种设备，根据设备的物理地址来划分网段，并传输数据的，docker0就是默认的网桥。</p> <p><strong>需求：</strong>
定制docker网桥</p> <p><strong>分析</strong>：
1、网桥的创建</p> <p>2、docker服务使用新网桥</p> <p>3、测试</p> <p><strong>知识点</strong>：
1、bridge-utils软件的brctl工具可以实现创建网桥
2、
​	配置/etc/default/docker文件
​	编辑systemctl的配置文件使用该docker文件
​	重载systemctl配置
​	重启docker
3、创建容器，查看容器信息即可</p> <p><strong>实施</strong>：</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#1、网桥环境部署</span>
    <span class="token comment">#1.1 网桥软件部署</span>
    <span class="token comment">#ubuntu默认不自带网桥管理工具，安装网桥软件</span>
    :~$ <span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> bridge-utils -y
    
    <span class="token comment">#查看网卡</span>
    :~$ brctl show
    bridge name  bridge <span class="token function">id</span>       STP enabled    interfaces 
    <span class="token comment">#网卡名称     网卡id           STP启用         物理接口</span>
    <span class="token comment">#1.2 创建网桥</span>
    :~$ <span class="token function">sudo</span> brctl addbr br0
    :~$ brctl show
    bridge name bridge <span class="token function">id</span>       STP enabled interfaces
    br0     <span class="token number">8000.000000000000</span>   no      

<span class="token comment">#给网桥设置网段</span>
    :~$ <span class="token function">sudo</span> <span class="token function">ifconfig</span> br0 <span class="token number">192.168</span>.99.1 netmask <span class="token number">255.255</span>.255.0
    :~$ <span class="token function">ifconfig</span>
    br0       Link encap:以太网  硬件地址 f2:6c:fb:c6:89:f4  
          inet 地址:192.168.99.1  广播:192.168.99.255  掩码:255.255.255.0

<span class="token comment">#2、docker配置网桥</span>
    <span class="token comment">#2.1    配置docker文件</span>
    :~$ <span class="token function">sudo</span> <span class="token function">vim</span> /etc/default/docker
    <span class="token comment">#最末尾添加</span>
    <span class="token assign-left variable">DOCKER_OPTS</span><span class="token operator">=</span><span class="token string">&quot;-b=br0&quot;</span>


<span class="token comment">#2.2    systemctl使用docker文件</span>
<span class="token comment">#创建服务依赖文件</span>
:~$ <span class="token function">sudo</span> <span class="token function">mkdir</span> -p /etc/systemd/system/docker.service.d
:~$ <span class="token function">sudo</span> <span class="token function">vim</span> /etc/systemd/system/docker.service.d/Using_Environment_File.conf
<span class="token comment">#内容如下：</span>
<span class="token punctuation">[</span>Service<span class="token punctuation">]</span>
<span class="token assign-left variable">EnvironmentFile</span><span class="token operator">=</span>-/etc/default/docker 
<span class="token assign-left variable">ExecStart</span><span class="token operator">=</span>
<span class="token assign-left variable">ExecStart</span><span class="token operator">=</span>/usr/bin/dockerd -H fd:// <span class="token variable">$DOCKER_OPTS</span>
<span class="token comment">#重载服务配置文件</span>
:~$ systemctl daemon-reload

<span class="token comment">#2.3    重启docker </span>
<span class="token comment">#重启前效果</span>
:~$ <span class="token function">ps</span> aux <span class="token operator">|</span><span class="token function">grep</span> docker 
root      <span class="token number">32949</span>  <span class="token number">0.1</span>  <span class="token number">1.4</span> <span class="token number">783160</span> <span class="token number">59632</span> ?        Ssl  <span class="token number">2</span>月24   <span class="token number">1</span>:01 /usr/bin/dockerd -H fd://

<span class="token comment">#重启</span>
:~$ systemctl restart docker

<span class="token comment">#重启后效果</span>
:~$ <span class="token function">ps</span> aux <span class="token operator">|</span><span class="token function">grep</span> docker 
root  <span class="token number">45737</span> <span class="token number">4.3</span>  <span class="token number">1.2</span> <span class="token number">527600</span> <span class="token number">50572</span> ?  Ssl 09:32 <span class="token number">0</span>:00 /usr/bin/dockerd -H fd:// -b<span class="token operator">=</span>br0

<span class="token comment">#3、容器测试</span>
    <span class="token comment">#3.1 创建容器并测试</span>
    <span class="token comment">#创建默认网络的容器</span>
    :~$ docker run -itd --name nginx--3 nginx
    92d4b5e434d2ba1a00426e987b113fdaa1dff82364240a9c498ee813529331b4
    
    :~$ docker <span class="token function">ps</span>
CONTAINERID  IMAGE COMMAND                CREATED      STATUS      PORTS    NAMES
92d4b5e434d2 nginx <span class="token string">&quot;nginx -g 'daemon of…&quot;</span> 5secondsago  Up4seconds  <span class="token number">80</span>/tcp   nginx--3
    
<span class="token comment">#查看信息已经使用了br0的网卡的网络</span>
:~$ docker inspect 92d4b5e434d2
                        <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;192.168.99.1&quot;</span>,
                        <span class="token string">&quot;IPAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;192.168.99.2&quot;</span>,
<span class="token comment">#查看下网络</span>
:~$ docker network <span class="token function">ls</span>
NETWORK ID          NAME                DRIVER              SCOPE
e2f5f07d1d54        bridge              bridge              <span class="token builtin class-name">local</span>

<span class="token comment">#查看网络下的容器</span>
:~$ docker network inspect bridge
 
        <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;bridge&quot;</span>,
        <span class="token string">&quot;Driver&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;bridge&quot;</span>,
            <span class="token string">&quot;Config&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">[</span>
                <span class="token punctuation">{</span>
                    <span class="token string">&quot;Subnet&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;192.168.99.0/24&quot;</span>,
                    <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;192.168.99.1&quot;</span>
        <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
            <span class="token string">&quot;92d4b5e434d2ba1a00426e987b113fdaa1dff82364240a9c498ee813529331b4&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx--3&quot;</span>,
                <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;b5c2e1ea9dcd722b102b7f63f569604cd65be378da649e8f8edd492c083cfec5&quot;</span>,
                <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;02:42:c0:a8:63:02&quot;</span>,
                <span class="token string">&quot;IPv4Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;192.168.99.2/24&quot;</span>,
</code></pre></div><h3 id="_2-4-8-host模型实践"><a href="#_2-4-8-host模型实践" class="header-anchor">#</a> 2.4.8 host模型实践</h3> <p>host模型我们知道，容器使用宿主机的ip地址进行对外提供服务，本身没有ip地址。</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
    docker run --net<span class="token operator">=</span>host -itd --name <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span> 镜像名称
<span class="token comment">#命令示例：</span>
    <span class="token comment">#查看下网络情况</span>
    :~$ docker network <span class="token function">ls</span>
    NETWORK ID          NAME                DRIVER              SCOPE
    35e1fe4bfd90        bridge              bridge              <span class="token builtin class-name">local</span>
    b5a84f949a9f        <span class="token function">host</span>                <span class="token function">host</span>                <span class="token builtin class-name">local</span>
    e70e4cb94db2        none                null                <span class="token builtin class-name">local</span>
    <span class="token comment">#查看host下有哪些容器</span>
    :~$ docker network  inspect  <span class="token function">host</span>
    <span class="token comment">#发现是空的</span>
            <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token comment">#查看宿主机启动网络</span>
    :~$ <span class="token function">netstat</span> -tnulp 
    <span class="token comment">#发现没有80端口  </span>
    <span class="token comment">#根据host网络创建启动容器</span>
    :~$ docker run --net<span class="token operator">=</span>host -itd --name nginx-1 nginx
    cf5f44228d7efa6271d494bc658a8073c1a3961dc0c7acab3c58796dfa925f6e
    :~$ docker <span class="token function">ps</span>
<span class="token comment">#发现没有端口映射</span>
CONTAINER ID    IMAGE    COMMAND                  CREATED             STATUS              PORTS   NAMES
cf5f44228d7e    nginx    <span class="token string">&quot;nginx -g 'daemon of…&quot;</span>   <span class="token number">15</span> minutes ago      Up <span class="token number">15</span> minutes               nginx-1
 
<span class="token comment">#查看宿主机启动网络</span>
:~$ <span class="token function">netstat</span> -tnulp 
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
<span class="token comment">#多出了80端口           </span>
tcp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">0.0</span>.0.0:80              <span class="token number">0.0</span>.0.0:*               LISTEN      -               
<span class="token comment">#查看host下有哪些容器</span>
:~$ docker network  inspect  <span class="token function">host</span>
<span class="token comment">#发现网络下包含了容器 nginx-1</span>
        <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;host&quot;</span>,
        <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
            <span class="token string">&quot;cf5f44228d7efa6271d494bc658a8073c1a3961dc0c7acab3c58796dfa925f6e&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx-1&quot;</span>,
                <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;98f3a7d052fabd7aa3e06c5a8d95d1db1ed28ffd81f7b0344b104217a505f94b&quot;</span>,
<span class="token comment">#查看nginx-1这个容器的全部信息</span>
:~$ docker inspect nginx-1 
 <span class="token comment">#发现网络信息为空</span>
    <span class="token string">&quot;Networks&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
            <span class="token string">&quot;host&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;IPAMConfig&quot;</span><span class="token builtin class-name">:</span> null,
                <span class="token string">&quot;Links&quot;</span><span class="token builtin class-name">:</span> null,
                <span class="token string">&quot;Aliases&quot;</span><span class="token builtin class-name">:</span> null,
                <span class="token string">&quot;NetworkID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;b5a84f949a9f2466430c7734a9e68d4499382efdee27886cb97bfdec0fb3834f&quot;</span>,
                <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;98f3a7d052fabd7aa3e06c5a8d95d1db1ed28ffd81f7b0344b104217a505f94b&quot;</span>,
                <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                <span class="token string">&quot;IPAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                <span class="token string">&quot;IPPrefixLen&quot;</span><span class="token builtin class-name">:</span> <span class="token number">0</span>,
                <span class="token string">&quot;IPv6Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                <span class="token string">&quot;GlobalIPv6Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                <span class="token string">&quot;GlobalIPv6PrefixLen&quot;</span><span class="token builtin class-name">:</span> <span class="token number">0</span>,
                <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                <span class="token string">&quot;DriverOpts&quot;</span><span class="token builtin class-name">:</span> null
</code></pre></div><p><strong>查看网络运行效果</strong>
http://192.168.110.4</p> <p><strong>此处IP为对应宿主机ip并不固定</strong></p> <p><img src="assets/1541591791777.png" alt="1541591791777"></p> <p><strong>host特点：</strong>
​	host模型比较适合于，一台宿主机跑一个固定的容器，比较稳定，或者一个宿主机跑多个占用不同端口的应用的场景，他的网络性能是很高的。
​	host模型启动的容器不会有任何地址，他其实是使用了宿主机的所有信息</p> <h3 id="_2-4-9-none-模型实践"><a href="#_2-4-9-none-模型实践" class="header-anchor">#</a> 2.4.9 none 模型实践</h3> <p>none网络模式，是一种自由度非常高的网络模式，我们可以最大化的自定义我们想要的网络</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#命令格式：</span>
     docker run --net<span class="token operator">=</span>none -itd --name <span class="token punctuation">[</span>容器名称<span class="token punctuation">]</span> 镜像名称     
<span class="token comment">#命令示例：</span>
    <span class="token comment">#查看网络</span>
    itcast@itcast-virtual-machine:~$ docker network <span class="token function">ls</span>
    NETWORK ID          NAME                DRIVER              SCOPE
    35e1fe4bfd90        bridge              bridge              <span class="token builtin class-name">local</span>
    b5a84f949a9f        <span class="token function">host</span>                <span class="token function">host</span>                <span class="token builtin class-name">local</span>
    e70e4cb94db2        none                null                <span class="token builtin class-name">local</span>
 
    <span class="token comment">#查看网络none的信息</span>
    :~$ docker  network inspect  none
    <span class="token comment">#发现包含容器为空</span>
            <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;none&quot;</span>,
            <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>,
 
    <span class="token comment">#根据none网络创建nginx-2容器</span>
    :~$ docker run -itd --name nginx-2 --net<span class="token operator">=</span>none nginx
    31b52114415459a415ffebb527aea43b857f4c4f82daaab363293a0a98cef713
 
    :~$ docker <span class="token function">ps</span>
CONTAINERID  IMAGE COMMAND             CREATED         STATUS         PORTS  NAMES
31b521144154 nginx <span class="token string">&quot;nginx-g'daemonof…&quot;</span> Aboutaminuteago UpAboutaminute      nginx-2
    <span class="token comment">#查看nginx-2的全部信息</span>
    :~$ docker inspect  nginx-2
    <span class="token comment">#发现网络信息皆为空 </span>
     <span class="token string">&quot;Networks&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                    <span class="token string">&quot;none&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                        <span class="token string">&quot;IPAMConfig&quot;</span><span class="token builtin class-name">:</span> null,
                        <span class="token string">&quot;Links&quot;</span><span class="token builtin class-name">:</span> null,
                        <span class="token string">&quot;Aliases&quot;</span><span class="token builtin class-name">:</span> null,
                        <span class="token string">&quot;NetworkID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;e70e4cb94db206011a26daa48331d376318fd6060ac20f027709d5e6b70fdbc2&quot;</span>,
                        <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;2bcba7434eee8ec827192b45bb0b0d2b71c916fd7da5a21562a34dca3726387a&quot;</span>,
                        <span class="token string">&quot;Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                        <span class="token string">&quot;IPAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                        <span class="token string">&quot;IPPrefixLen&quot;</span><span class="token builtin class-name">:</span> <span class="token number">0</span>,
                        <span class="token string">&quot;IPv6Gateway&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                        <span class="token string">&quot;GlobalIPv6Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                        <span class="token string">&quot;GlobalIPv6PrefixLen&quot;</span><span class="token builtin class-name">:</span> <span class="token number">0</span>,
                        <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                        <span class="token string">&quot;DriverOpts&quot;</span><span class="token builtin class-name">:</span> null
                    <span class="token punctuation">}</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">]</span>
    :~$ docker network inspect none
    <span class="token comment">#none网络下有none的网络下包含容器 nginx-2并且没有网络信息</span>
    <span class="token punctuation">[</span>
        <span class="token punctuation">{</span>
            <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;none&quot;</span>,
            <span class="token string">&quot;Containers&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                <span class="token string">&quot;31b52114415459a415ffebb527aea43b857f4c4f82daaab363293a0a98cef713&quot;</span><span class="token builtin class-name">:</span> <span class="token punctuation">{</span>
                    <span class="token string">&quot;Name&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;nginx-2&quot;</span>,
                    <span class="token string">&quot;EndpointID&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;2bcba7434eee8ec827192b45bb0b0d2b71c916fd7da5a21562a34dca3726387a&quot;</span>,
                    <span class="token string">&quot;MacAddress&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                    <span class="token string">&quot;IPv4Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>,
                    <span class="token string">&quot;IPv6Address&quot;</span><span class="token builtin class-name">:</span> <span class="token string">&quot;&quot;</span>
                <span class="token punctuation">}</span>
 
    :~$ <span class="token function">netstat</span> -tnulp
    <span class="token comment">#发现并没有80端口的网络启动</span>
Proto Recv-Q Send-Q Local Address      Foreign Address   State      PID/Program name
    tcp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">127.0</span>.1.1:53   <span class="token number">0.0</span>.0.0:*         LISTEN     -               
    tcp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">0.0</span>.0.0:22     <span class="token number">0.0</span>.0.0:*         LISTEN     -               
    tcp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">127.0</span>.0.1:631  <span class="token number">0.0</span>.0.0:*         LISTEN     -                             
    tcp6       <span class="token number">0</span>      <span class="token number">0</span> :::22          :::*              LISTEN     -               
    tcp6       <span class="token number">0</span>      <span class="token number">0</span> ::1:631        :::*              LISTEN     -               
    udp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">127.0</span>.1.1:53   <span class="token number">0.0</span>.0.0:*                           -               
    udp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">0.0</span>.0.0:45194  <span class="token number">0.0</span>.0.0:*                           -               
    udp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">0.0</span>.0.0:631    <span class="token number">0.0</span>.0.0:*                           -               
    udp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">0.0</span>.0.0:39822  <span class="token number">0.0</span>.0.0:*                           -               
    udp        <span class="token number">0</span>      <span class="token number">0</span> <span class="token number">0.0</span>.0.0:5353   <span class="token number">0.0</span>.0.0:*                           -               
    udp6       <span class="token number">0</span>      <span class="token number">0</span> :::56067       :::*                                -               
    udp6       <span class="token number">0</span>      <span class="token number">0</span> :::5353        :::*                                -               

</code></pre></div><h3 id="_2-4-10-none案例-自定义桥接网络"><a href="#_2-4-10-none案例-自定义桥接网络" class="header-anchor">#</a> 2.4.10 none案例--自定义桥接网络</h3> <p>**配置自定义桥接网络案例 **
为了使本地网络中和Docker容器更方便的通信，我们经常会有将Docker容器配置到和主机同一网段，而且还要指定容器的ip地址。</p> <p><strong>需求</strong>：
自定义容器网络和宿主机为同一网段，容器ip可以指定。</p> <p><strong>案例分析：</strong>
1、自定义容器网络段和宿主机一样</p> <p>2、自定义容器ip地址
<strong>知识关键点：</strong>
1、网络配置</p> <p>docker虚拟网桥配置</p> <p>docker服务使用网桥</p> <p>容器创建使用none模式</p> <p>2、使用pipwork工具实现定制docker容器ip地址</p> <p>注释：pipwork的命令格式</p> <p>pipework [桥接设备][容器id或者名字] [容器ip]/[ip掩码]@[宿主机网关]</p> <p>例子：</p> <p>pipework br0 ubuntu-test1 192.168.8.201/24@192.168.8.2</p> <p>3、映射虚拟机软件源进入到容器，替换掉容器内部软件源后进行软件源更新与安装</p> <p>注释：docker上pull下来的Ubuntu,使用apt-get  install 命令下载速度奇慢无比,需要修改其软件源,进入etc/apt</p> <p>目录欲修改sources.list     发现vi,vim,gedit都没有,再下这些软件也非常慢.</p> <p>解决方法：</p> <p>3.1启动容器时,挂载本地Linux系统的etc/apt文件</p> <p>docker run -ti -v /etc/apt/:/home/etc ubuntu</p> <p>3.2删除容器下的sources.lis   rm /etc/apt/sources.list</p> <p>3.3将本地sources.list 复制过来 cp /home/etc/sources.list  /etc/apt/</p> <p><strong>自定义桥接网络实施</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#1、网络环境部署</span>
<span class="token comment">#1.1 网卡环境部署</span>
<span class="token comment">#1.1.1 网桥软件部署</span>
	:~$ <span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> bridge-utils -y
	
	:~$ brctl show
	bridge  name    bridge <span class="token function">id</span>           STP enabled interfaces
	docker0         <span class="token number">8000</span>.0242a6e980f2   no      
	 
<span class="token comment">#1.1.2 桥接网卡配置</span>
<span class="token comment">#编辑网卡信息编辑Ubuntu的网卡信息文件</span>
<span class="token comment">#对源文件进行备份</span>
	:~$ <span class="token function">sudo</span> <span class="token function">cp</span> /etc/network/interfaces /etc/network/interfaces-old
	:~$ <span class="token function">sudo</span> <span class="token function">vim</span> /etc/network/interfaces
	
<span class="token comment">#与源文件内容进行1行的空行</span>
auto br0
iface br0 inet static 
address <span class="token number">192.168</span>.110.14
netmask <span class="token number">255.255</span>.255.0
gateway <span class="token number">192.168</span>.110.2
dns-nameservers <span class="token number">192.168</span>.110.2 
bridge_ports ens33
<span class="token comment">#重启</span>
<span class="token function">service</span> networking restart
    
<span class="token comment">#1.2    docker服务配置</span>
    <span class="token comment">#1.2.1  配置docker文件</span>
    :~$ <span class="token function">sudo</span> <span class="token function">vim</span> /etc/default/docker
    <span class="token comment">#最末尾添加</span>
    <span class="token assign-left variable">DOCKER_OPTS</span><span class="token operator">=</span><span class="token string">&quot;-b=br0&quot;</span>
    
    <span class="token comment">#1.2.2  systemctl使用docker文件</span>
    <span class="token comment">#创建服务依赖文件</span>
    :~$ <span class="token function">sudo</span> <span class="token function">mkdir</span> -p /etc/systemd/system/docker.service.d
    :~$ <span class="token function">sudo</span> <span class="token function">vim</span> /etc/systemd/system/docker.service.d/Using_Environment_File.conf
    <span class="token comment">#内容如下：</span>
<span class="token punctuation">[</span>Service<span class="token punctuation">]</span>
<span class="token assign-left variable">EnvironmentFile</span><span class="token operator">=</span>-/etc/default/docker
<span class="token assign-left variable">ExecStart</span><span class="token operator">=</span>
<span class="token assign-left variable">ExecStart</span><span class="token operator">=</span>/usr/bin/dockerd -H fd:// <span class="token variable">$DOCKER_OPTS</span>
    <span class="token comment">#重载服务配置文件</span>
    :~$ systemctl daemon-reload
<span class="token comment">#1.2.3  重启docker 第一次配置的时候需要重启linux虚拟机：reboot</span>
systemctl restart docker

<span class="token comment">#注意查看网卡信息</span>
    :~$ brctl show
    bridge      name    bridge <span class="token function">id</span>           STP enabled     interfaces
    br0                 <span class="token number">8000</span>.000c2960060c   no              ens33
    docker0             <span class="token number">8000</span>.02427c11f899   no  
    
    br0       Link encap:以太网  硬件地址 00:0c:29:60:06:0c  
         inet 地址:192.168.110.14  广播:192.168.110.255  掩码:255.255.255.0
         inet6 地址: fe80::20c:29ff:fe60:60c/64 Scope:Link
         UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
     
    ens33     Link encap:以太网  硬件地址 00:0c:29:60:06:0c  
      UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
<span class="token comment">#广播运行多播</span>

<span class="token comment">#验证dns解析是否正常</span>
    <span class="token function">ping</span> www.baidu.com   
<span class="token comment">#网络可能会没有dns解析所以我们需要进行dns的配置</span>

<span class="token comment">#16.04：</span>
:~$ <span class="token function">sudo</span> vim/etc/resolvconf/resolv.conf.d/base
<span class="token comment">#18.04：</span>
:~$ <span class="token function">sudo</span> vim/etc/resolv.conf

<span class="token comment">#增加内容</span>
nameserver <span class="token number">223.5</span>.5.5
nameserver <span class="token number">114.114</span>.114.114
nameserver <span class="token number">8.8</span>.8.8

<span class="token comment">#注意如果重启后网络并未生效则</span>
    <span class="token function">sudo</span> /etc/init.d/networking restart

<span class="token comment">#1.3 容器创建</span>
    <span class="token comment">#基于ubuntu镜像创建一个容器，网络模式使用none ，启动容器时,挂载本地Linux系统的etc/apt文件</span>
    :~$ docker run -itd --net<span class="token operator">=</span>none --name ubuntu-test1 -v /etc/apt/:/home/etc   ubuntu  /bin/bash
    5f7b976ddfdf60dbc08cb81569488b70da15bc183d7f21da7030c316cd6ec96b
    :~$ docker <span class="token function">ps</span>
    CONTAINER ID  IMAGE     COMMAND      CREATED             STATUS          PORTS   NAMES
    5f7b976ddfdf  ubuntu    <span class="token string">&quot;/bin/bash&quot;</span>  <span class="token number">5</span> seconds ago       Up <span class="token number">4</span> seconds            ubuntu-test1
        
<span class="token comment">#2、定制容器ip</span>
    <span class="token comment">#2.1 pipwork软件部署</span>
    <span class="token comment">#安装pipwork</span>
    <span class="token comment">#方法1：</span>
    <span class="token function">git</span> clone https://github.com/jpetazzo/pipework
    <span class="token comment">#方法2：将软件直接拖入ubuntu虚拟机</span>
    <span class="token comment">#直接解压安装包</span>
    :~<span class="token variable">$unzip</span> pipework-master.zip
    <span class="token comment">#将文件拷贝到bin下</span>
    <span class="token function">sudo</span> <span class="token function">cp</span> pipework-master/pipework /usr/local/bin/
    
    <span class="token comment">#2.2 定制容器ip</span>
    :~$ <span class="token function">sudo</span> pipework br0 ubuntu-test1 <span class="token number">192.168</span>.110.129/24@192.168.110.2
    
    <span class="token comment">#2.3 测试效果</span>
    <span class="token comment">#进入容器查看ip地址信息</span>
    :~$ docker <span class="token builtin class-name">exec</span> -it ubuntu-test1 /bin/bash
    
    <span class="token comment">#删除容器下的sources.lis</span>
    :~<span class="token comment"># rm /etc/apt/sources.list</span>
    <span class="token comment">#将本地sources.list 复制过来</span>
    :~<span class="token comment"># cp /home/etc/sources.list  /etc/apt/</span>
    <span class="token comment">#进行软件源更新</span>
    :~<span class="token comment"># apt-get update</span>
    <span class="token comment">#安装ping命令</span>
    :~<span class="token comment"># apt-get install inetutils-ping -y</span>
    <span class="token comment">#安装ifconfig命令</span>
    :~<span class="token comment"># apt-get install net-tools -y</span>
    宿主机ping命令测试
    <span class="token operator">&gt;</span> <span class="token function">ping</span> <span class="token number">192.168</span>.110.14
</code></pre></div><h3 id="_2-4-11-跨主机容器通信"><a href="#_2-4-11-跨主机容器通信" class="header-anchor">#</a> 2.4.11 跨主机容器通信</h3> <p>容器网络拓扑图</p> <p><img src="assets/1541592121462.png" alt="1541592121462"></p> <p>主机信息：</p> <p>主机1：ubuntu 18.04 192.168.8.14</p> <p>主机2：ubuntu 16.04 192.168.8.15</p> <p>均安装 bridge-utils软件</p> <p>分析：
1、自定义br0</p> <p>2、docker服务使用br0</p> <p>3、创建容器使用br0</p> <p>4、跨主机间网络测试</p> <p>知识点：
1、使用手工方式定制ubuntu的网卡</p> <p>2、
配置/etc/default/docker文件</p> <p>编辑systemctl的配置文件使用该docker文件</p> <p>重载systemctl配置</p> <p>重启docker或者重启虚拟机</p> <p>3、创建容器，查看容器信息即可</p> <p>4、两台主机分别测试</p> <p>注意：
1、2、3 这三条在两台主机的配置大部分一模一样
ip地址划分不一样</p> <p>方案：
1、ubuntu桥接网卡配置</p> <p>1.1 软件安装</p> <p>1.2 编辑网卡</p> <p>2、docker配置网桥</p> <p>2.1 配置docker文件</p> <p>2.2 systemctl使用docker文件</p> <p>2.3 重启主机</p> <p>3、容器测试</p> <p>3.1 创建容器</p> <p>3.2 容器间测试</p> <p>实施：</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#1、ubuntu桥接网卡配置</span>
    <span class="token comment">#1.1 软件安装</span>
    <span class="token function">apt-get</span> <span class="token function">install</span> bridge-utils -y
    <span class="token comment">#1.2 编辑网卡</span>
    :~$ <span class="token function">sudo</span> <span class="token function">vim</span> /etc/network/interfaces
    <span class="token comment">#与文件源内容进行1行的空行</span>
    <span class="token comment">#主机1</span>
auto br0
iface br0 inet static
address <span class="token number">192.168</span>.110.14
netmask <span class="token number">255.255</span>.255.0
gateway <span class="token number">192.168</span>.110.2
dns-nameservers <span class="token number">192.168</span>.110.2
bridge_ports ens33
    <span class="token comment">#主机2</span>
    auto br0
    iface br0 inet static
    address <span class="token number">192.168</span>.110.15
    netmask <span class="token number">255.255</span>.255.0
    gateway <span class="token number">192.168</span>.110.2
    dns-nameservers <span class="token number">192.168</span>.110.2
    bridge_ports ens33
    
<span class="token comment">#2、docker配置网桥</span>
    <span class="token comment">#2.1 配置docker文件</span>
    <span class="token comment">#修改docker的守护进程文件</span>
    <span class="token function">vim</span> /etc/default/docker
    <span class="token comment">#末尾添加:</span>
    <span class="token comment">#主机1</span>
    <span class="token assign-left variable">DOCKER_OPTS</span><span class="token operator">=</span><span class="token string">&quot;-b=br0 --fixed-cidr=192.168.110.99/26&quot;</span>
    <span class="token comment">#主机2</span>
    <span class="token assign-left variable">DOCKER_OPTS</span><span class="token operator">=</span><span class="token string">&quot;-b=br0 --fixed-cidr=192.168.110.170/26&quot;</span>    
    <span class="token comment">#注释：</span>
    <span class="token comment">#-b 用来指定容器连接的网桥名字</span>
    <span class="token comment">#--fixed-cidr用来限定为容器分配的IP地址范围</span>
    <span class="token comment">#192.168.110.99/26地址范围：192.168.110.64~192.168.110.127</span>
    <span class="token comment">#192.168.110.170/26地址范围：192.168.110.128~192.168.110.191</span>
    <span class="token comment">#网段的计算可以参考网址：http://help.bitscn.com/ip/</span>
    
    <span class="token comment">#2.2 systemctl使用docker文件</span>
    创建服务依赖文件
    :~$ <span class="token function">sudo</span> <span class="token function">mkdir</span> -p /etc/systemd/system/docker.service.d
    :~$ <span class="token function">sudo</span> <span class="token function">vim</span> /etc/systemd/system/docker.service.d/Using_Environment_File.conf
    内容如下：
<span class="token punctuation">[</span>Service<span class="token punctuation">]</span>
<span class="token assign-left variable">EnvironmentFile</span><span class="token operator">=</span>-/etc/default/docker
<span class="token assign-left variable">ExecStart</span><span class="token operator">=</span>
<span class="token assign-left variable">ExecStart</span><span class="token operator">=</span>/usr/bin/dockerd -H fd:// <span class="token variable">$DOCKER_OPTS</span>
    <span class="token comment">#重载服务配置文件</span>
    :~<span class="token variable">$systemctl</span> daemon-reload
    <span class="token comment">#2.3 重启主机</span>
    <span class="token function">reboot</span>
    <span class="token comment">#注意如果重启后网络并未生效则</span>
    <span class="token function">sudo</span> /etc/init.d/networking restart
    <span class="token comment">#注意查看网卡信息</span>
    :~$ brctl show
    bridge      name    bridge <span class="token function">id</span>           STP enabled     interfaces
    br0                 <span class="token number">8000</span>.000c2960060c   no              ens33
    docker0             <span class="token number">8000</span>.02427c11f899   no  
    
    br0       Link encap:以太网  硬件地址 00:0c:29:60:06:0c  
         inet 地址:192.168.110.14  广播:192.168.110.255  掩码:255.255.255.0
         inet6 地址: fe80::20c:29ff:fe60:60c/64 Scope:Link
         UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
     


ens33     Link encap:以太网  硬件地址 00:0c:29:60:06:0c  
  UP BROADCAST RUNNING MULTICAST  MTU:1500  跃点数:1
<span class="token comment">#广播运行多播</span>


广播运行多播
<span class="token comment">#验证dns解析是否正常 </span>
    <span class="token function">ping</span> www.baidu.com 
<span class="token comment">#网络可能会没有dns解析所以我们需要进行dns的配置</span>
<span class="token comment">#16.04：</span>
:~$ <span class="token function">sudo</span> vim/etc/resolvconf/resolv.conf.d/base
<span class="token comment">#18.04：</span>
:~$ <span class="token function">sudo</span> vim/etc/resolv.conf
<span class="token comment">#增加内容</span>
nameserver <span class="token number">223.5</span>.5.5
nameserver <span class="token number">114.114</span>.114.114
nameserver <span class="token number">8.8</span>.8.8
 <span class="token comment">#注意如果重启后网络并未生效则</span>
    <span class="token function">sudo</span> /etc/init.d/networking restart

<span class="token comment">#3、容器测试</span>
    <span class="token comment">#3.1 创建容器</span>
    
    <span class="token comment">#主机1：</span>
    :~$ docker run -itd --name ubuntu-test1 -v /etc/apt/:/home/etc ubuntu /bin/bash
    :~$ docker run -itd --name ubuntu-test2 -v /etc/apt/:/home/etc ubuntu /bin/bash
    <span class="token comment">#主机2                                                                      </span>
    :~$ docker run -itd --name ubuntu-test3 -v /etc/apt/:/home/etc ubuntu /bin/bash
    :~$ docker run -itd --name ubuntu-test4 -v /etc/apt/:/home/etc ubuntu /bin/bash
    <span class="token comment">#3.2 容器间测试</span>
    进入容器
    <span class="token comment">#主机1</span>
    :~<span class="token variable">$docker</span> <span class="token builtin class-name">exec</span> -it ubuntu-test1 /bin/bash
    :~<span class="token variable">$docker</span> <span class="token builtin class-name">exec</span> -it ubuntu-test2 /bin/bash
    <span class="token comment">#主机2</span>
    :~<span class="token variable">$docker</span> <span class="token builtin class-name">exec</span> -it ubuntu-test3 /bin/bash
    :~<span class="token variable">$docker</span> <span class="token builtin class-name">exec</span> -it ubuntu-test4 /bin/bash

:~<span class="token comment"># rm /etc/apt/sources.list</span>
<span class="token comment">#容器内部将本地sources.list 复制过来</span>
:~<span class="token comment"># cp /home/etc/sources.list /etc/apt/</span>
<span class="token comment">#容器内部进行软件源更新</span>
:~<span class="token comment"># apt-get update</span>
<span class="token comment">#容器内部安装ping命令</span>
:~<span class="token comment"># apt-get install inetutils-ping -y</span>
<span class="token comment">#容器内部安装ifconfig命令</span>
:~<span class="token comment"># apt-get install net-tools -y</span>

<span class="token comment">#四个容器之间相互ping通</span>

宿主机ping命令测试
<span class="token operator">&gt;</span> <span class="token function">ping</span> <span class="token number">192.168</span>.110.14
<span class="token operator">&gt;</span> <span class="token function">ping</span> <span class="token number">192.168</span>.110.15


</code></pre></div><p>总结：
优点：
配置简单，不依赖第三方软件
缺点：
容器依赖于主机间的网络
容器与主机在同网段，注意ip地址分配
生产中不容易实现、不好管理
​</p> <h1 id="第-3-章-docker-高级实践"><a href="#第-3-章-docker-高级实践" class="header-anchor">#</a> 第 3 章 Docker 高级实践</h1> <p><img src="assets/timg.jpg" alt="img"></p> <p>在这一部分我们来介绍一些Docker的高级内容：
Dockerfile 和 Docker compose</p> <h2 id="_3-1-dockerfile"><a href="#_3-1-dockerfile" class="header-anchor">#</a> 3.1 Dockerfile</h2> <h3 id="_3-1-1-dockerfile简介"><a href="#_3-1-1-dockerfile简介" class="header-anchor">#</a> 3.1.1 Dockerfile简介</h3> <p><strong>什么是Dockerfile</strong>
​	Dockerfile类似于我们学习过的脚本，将我们在上面学到的docker镜像，使用自动化的方式实现出来。</p> <p>注意事项:</p> <ul><li>文件名首字母大写</li> <li>存储Dockerfile的目录, 尽量是空目录</li> <li>制作的镜像功能尽量单一</li> <li>制作步骤要尽可能精简</li></ul> <p><strong>dockerfile的组成</strong></p> <blockquote><p>dockerfile中的注释使用: #</p></blockquote> <ul><li>基础镜像信息
<ul><li>要制作的新的镜像, 基于那个镜像来制作的</li> <li>通过 docker images 查看</li></ul></li> <li>维护者信息
<ul><li>这个dockerfile是谁写的</li></ul></li> <li>镜像操作指令
<ul><li>基于原始进行进行的操作</li></ul></li> <li>容器启动指令
<ul><li>基于第三步得到了新镜像</li> <li>新的镜像启动之后, 在容器中默认执行的指令</li></ul></li></ul> <p><strong>Dockerfile使用命令：</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#构建镜像命令格式：</span>
docker build -t <span class="token punctuation">[</span>镜像名<span class="token punctuation">]</span>:<span class="token punctuation">[</span>版本号<span class="token punctuation">]</span><span class="token punctuation">[</span>Dockerfile所在目录<span class="token punctuation">]</span>
<span class="token comment">#构建样例：</span>
docker build -t nginx:v0.2 /opt/dockerfile/nginx/
<span class="token comment">#参数详解：</span>
	-t        					指定构建后的镜像信息，
	/opt/dockerfile/nginx/      则代表Dockerfile存放位置，如果是当前目录，则用 .<span class="token punctuation">(</span>点<span class="token punctuation">)</span>表示
</code></pre></div><h3 id="_3-1-2-dockerfile快速入门"><a href="#_3-1-2-dockerfile快速入门" class="header-anchor">#</a> 3.1.2 Dockerfile快速入门</h3> <p>​	接下来我们快速的使用Dockerfile来基于ubuntu创建一个定制化的镜像：nginx。</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#创建Dockerfile专用目录</span>
:~$ <span class="token function">mkdir</span> ./docker/images/nginx -p
:~$ <span class="token builtin class-name">cd</span> docker/images/nginx/
<span class="token comment">#创建Dockerfile文件</span>
:~/docker/images/nginx$ <span class="token function">vim</span> Dockerfile
</code></pre></div><p><strong>dockerfile内容</strong></p> <div class="language-Dockerfile extra-class"><pre class="language-dockerfile"><code><span class="token comment"># 构建一个基于ubuntu的docker定制镜像</span>
<span class="token comment"># 基础镜像</span>
<span class="token keyword">FROM</span> ubuntu

<span class="token comment"># 镜像作者</span>
<span class="token keyword">MAINTAINER</span> panda kstwoak47@163.com

<span class="token comment"># 执行命令</span>
<span class="token keyword">RUN</span> mkdir hello
<span class="token keyword">RUN</span> mkdir world
<span class="token keyword">RUN</span> sed <span class="token punctuation">-</span>i <span class="token string">'s/archive.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list
<span class="token keyword">RUN</span> sed <span class="token punctuation">-</span>i <span class="token string">'s/security.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list
<span class="token keyword">RUN</span> apt<span class="token punctuation">-</span>get update  
<span class="token keyword">RUN</span> apt<span class="token punctuation">-</span>get install nginx <span class="token punctuation">-</span>y

<span class="token comment"># 对外端口</span>
<span class="token keyword">EXPOSE</span> 80
</code></pre></div><p><strong>进行构建操作</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#构建镜像</span>
:~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.1 <span class="token builtin class-name">.</span>
<span class="token comment">#查看新生成镜像</span>
:~/docker/images/nginx$ docker images
REPOSITORY    TAG     IMAGE ID      CREATED        SIZE
ubuntu-nginx  v0.1    a853de1b8be4  <span class="token number">9</span> seconds ago  208MB
nginx         latest  e548f1a579cf  <span class="token number">6</span> days ago     109MB
ubuntu        latest  0458a4468cbc  <span class="token number">4</span> weeks ago    112MB
<span class="token comment">#查看构建历史</span>
:~/docker/images/nginx$ docker <span class="token function">history</span> a853de1b8be4
IMAGE         CREATED            CREATED BY                         SIZE   COMMENT
<span class="token comment">#镜像			创建时间             依赖命令                            大小    评论</span>
a853de1b8be4  <span class="token number">41</span> seconds ago     /bin/sh -c <span class="token comment">#(nop)  EXPOSE 80                  0B      </span>
925825b680fd  <span class="token number">42</span> seconds ago     /bin/sh -c <span class="token function">apt-get</span> <span class="token function">install</span> nginx -y          <span class="token number">56</span>.5MB  
4c57d6c99603  About a minute ago /bin/sh -c <span class="token function">apt-get</span> update                     40MB    
b6d030a0d123  About a minute ago /bin/sh -c <span class="token function">sed</span> -i<span class="token string">'s/security.ubuntu.com/mir… 2.77kB  
3357bf8069ca  About a minute ago /bin/sh -c sed -i'</span>s/archive.ubuntu.com/mirr… <span class="token number">2</span>.77kB  
7bfb90c1e20d  About a minute ago /bin/sh -c <span class="token function">mkdir</span> world                         0B      
972d6ab76d01  About a minute ago /bin/sh -c <span class="token function">mkdir</span> hello                         0B      
a76394bfad01  About a minute ago /bin/sh -c <span class="token comment">#(nop) MAINTAINER panda kstwoak4…  0B    </span>
<span class="token comment">#注意：</span>
因为容器没有启动命令，所以肯定访问不了

</code></pre></div><p><strong>优化刚刚的Dockerfile文件</strong></p> <div class="language-Dockerfile extra-class"><pre class="language-dockerfile"><code><span class="token comment"># 构建一个基于ubuntu的docker定制镜像</span>
<span class="token comment"># 基础镜像</span>
<span class="token keyword">FROM</span> ubuntu

<span class="token comment"># 镜像作者</span>
<span class="token keyword">MAINTAINER</span> panda kstwoak47@163.com

<span class="token comment"># 执行命令</span>
<span class="token keyword">RUN</span> mkdir hello
<span class="token keyword">RUN</span> mkdir world
<span class="token keyword">RUN</span> sed <span class="token punctuation">-</span>i <span class="token string">'s/archive.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list
<span class="token keyword">RUN</span> sed <span class="token punctuation">-</span>i <span class="token string">'s/security.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list
<span class="token keyword">RUN</span> apt<span class="token punctuation">-</span>get update  
<span class="token keyword">RUN</span> apt<span class="token punctuation">-</span>get install nginx <span class="token punctuation">-</span>y

<span class="token comment"># 对外端口</span>
<span class="token keyword">EXPOSE</span> 80
</code></pre></div><p><strong>运行修改好的Dockerfile进行构建</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code>:~/docker/images/nginx$ docker build -t  ubuntu-nginx:v0.2 <span class="token builtin class-name">.</span>
:~/docker/images/nginx$ docker <span class="token function">history</span> ubuntu-nginx:v0.2
IMAGE         CREATED         CREATED BY                                     SIZE    COMMENT
eaba9bd1c4ac  <span class="token number">3</span> minutes ago   /bin/sh -c <span class="token comment">#(nop)  EXPOSE 80                   0B      </span>
ed08d6e29eb1  <span class="token number">3</span> minutes ago   /bin/sh -c <span class="token function">apt-get</span> update <span class="token operator">&amp;&amp;</span> <span class="token function">apt-get</span> install…  <span class="token number">96</span>.5MB  
eef6238ec5bd  <span class="token number">6</span> minutes ago   /bin/sh -c <span class="token function">sed</span> -i 's/archive.ubuntu.com/mirr…  <span class="token number">2</span>.77kB  
58f755a1b29c  <span class="token number">6</span> minutes ago   /bin/sh -c <span class="token function">mkdir</span> hello <span class="token operator">&amp;&amp;</span>  <span class="token function">mkdir</span> world         0B      
a76394bfad01  <span class="token number">25</span> minutes ago  /bin/sh -c <span class="token comment">#(nop)  MAINTAINER panda kstwoak4…  0B    </span>
<span class="token comment">#对比两个镜像的大小</span>
:~/docker/images/nginx$ docker images 
REPOSITORY    TAG   IMAGE ID      CREATED         SIZE
ubuntu-nginx  v0.2  eaba9bd1c4ac  <span class="token number">7</span> seconds ago   208MB
ubuntu-nginx  v0.1  a853de1b8be4  <span class="token number">21</span> minutes ago  208MB
<span class="token comment">#深度对比连个镜像的大小</span>
:~/docker/images/nginx$ docker inspect a853de1b8be4
        <span class="token string">&quot;Size&quot;</span><span class="token builtin class-name">:</span> <span class="token number">208237435</span>,
        <span class="token string">&quot;VirtualSize&quot;</span><span class="token builtin class-name">:</span> <span class="token number">208237435</span>,
:~/docker/images/nginx$ docker inspect eaba9bd1c4ac
        <span class="token string">&quot;Size&quot;</span><span class="token builtin class-name">:</span> <span class="token number">208234662</span>,
        <span class="token string">&quot;VirtualSize&quot;</span><span class="token builtin class-name">:</span> <span class="token number">208234662</span>,
</code></pre></div><p><strong>Dockerfile构建过程：</strong>
​	从基础镜像1运行一个容器A</p> <p>​	遇到一条Dockerfile指令，都对容器A做一次修改操作</p> <p>​	执行完毕一条命令，提交生成一个新镜像2</p> <p>​	再基于新的镜像2运行一个容器B</p> <p>​	遇到一条Dockerfile指令，都对容器B做一次修改操作</p> <p>​	执行完毕一条命令，提交生成一个新镜像3</p> <p>​	…</p> <p>**构建过程镜像介绍</p> <p>​       构建过程中，创建了很多镜像，这些中间镜像，我们可以直接使用来启动容器，通过查看容器效果，从侧面能看到我们每次构建的效果。提供了镜像调试的能力</p> <h3 id="_3-1-3-基础指令详解"><a href="#_3-1-3-基础指令详解" class="header-anchor">#</a> 3.1.3 基础指令详解</h3> <h4 id="from"><a href="#from" class="header-anchor">#</a> <strong>FROM</strong></h4> <div class="language-shell extra-class"><pre class="language-shell"><code>FROM
<span class="token comment">#格式：</span>
    FROM <span class="token operator">&lt;</span>image<span class="token operator">&gt;</span>
    FROM <span class="token operator">&lt;</span>image<span class="token operator">&gt;</span>:<span class="token operator">&lt;</span>tag<span class="token operator">&gt;</span>
<span class="token comment">#解释：</span>
    <span class="token comment">#FROM 是 Dockerfile 里的第一条而且只能是除了首行注释之外的第一条指令</span>
    <span class="token comment">#可以有多个FROM语句，来创建多个image</span>
    <span class="token comment">#FROM 后面是有效的镜像名称，如果该镜像没有在你的本地仓库，那么就会从远程仓库Pull取，如果远程也没有，就报错失败</span>
    <span class="token comment">#下面所有的 系统可执行指令 在 FROM 的镜像中执行。</span>

 
</code></pre></div><h4 id="maintainer"><a href="#maintainer" class="header-anchor">#</a> <strong>MAINTAINER</strong></h4> <div class="language-shell extra-class"><pre class="language-shell"><code>MAINTAINER
<span class="token comment">#格式：</span>
    MAINTAINER <span class="token operator">&lt;</span>name<span class="token operator">&gt;</span>
<span class="token comment">#解释：</span>
    <span class="token comment">#指定该dockerfile文件的维护者信息。类似我们在docker commit 时候使用-a参数指定的信息</span>
</code></pre></div><h4 id="run"><a href="#run" class="header-anchor">#</a> <strong>RUN</strong></h4> <div class="language-shell extra-class"><pre class="language-shell"><code>RUN
<span class="token comment">#格式：</span>
    RUN <span class="token operator">&lt;</span>command<span class="token operator">&gt;</span>                                   <span class="token punctuation">(</span>shell模式<span class="token punctuation">)</span>
    RUN<span class="token punctuation">[</span><span class="token string">&quot;executable&quot;</span>, <span class="token string">&quot;param1&quot;</span>, <span class="token string">&quot;param2&quot;</span><span class="token punctuation">]</span>            <span class="token punctuation">(</span>exec 模式<span class="token punctuation">)</span>
<span class="token comment">#解释：</span>
    <span class="token comment">#表示当前镜像构建时候运行的命令，如果有确认输入的话，一定要在命令中添加 -y</span>
    <span class="token comment">#如果命令较长，那么可以在命令结尾使用 \ 来换行</span>
    <span class="token comment">#生产中，推荐使用上面数组的格式</span>
<span class="token comment">#注释：</span>
    <span class="token comment">#shell模式：类似于  /bin/bash -c command</span>
    <span class="token comment">#举例： RUN echo hello</span>
    <span class="token comment">#exec模式：类似于 RUN[&quot;/bin/bash&quot;, &quot;-c&quot;, &quot;command&quot;]</span>
    <span class="token comment">#举例： RUN[&quot;echo&quot;, &quot;hello&quot;]</span>
</code></pre></div><h4 id="expose"><a href="#expose" class="header-anchor">#</a> <strong>EXPOSE</strong></h4> <div class="language-shell extra-class"><pre class="language-shell"><code>EXPOSE
<span class="token comment">#格式：</span>
    EXPOSE <span class="token operator">&lt;</span>port<span class="token operator">&gt;</span> <span class="token punctuation">[</span><span class="token operator">&lt;</span>port<span class="token operator">&gt;</span><span class="token punctuation">..</span>.<span class="token punctuation">]</span>
<span class="token comment">#解释：</span>
    设置Docker容器对外暴露的端口号，Docker为了安全，不会自动对外打开端口，如果需要外部提供访问，
    还需要启动容器时增加-p或者-P参数对容器的端口进行分配。
<span class="token comment">#     docker run -itd -p 8888:80</span>
  EXPOSE <span class="token number">80</span>
</code></pre></div><h3 id="_3-1-4-运行时指令详解"><a href="#_3-1-4-运行时指令详解" class="header-anchor">#</a> 3.1.4 运行时指令详解</h3> <h4 id="cmd"><a href="#cmd" class="header-anchor">#</a> <strong>CMD</strong></h4> <div class="language-shell extra-class"><pre class="language-shell"><code>CMD
<span class="token comment">#格式：</span>
    CMD <span class="token punctuation">[</span><span class="token string">&quot;executable&quot;</span>,<span class="token string">&quot;param1&quot;</span>,<span class="token string">&quot;param2&quot;</span><span class="token punctuation">]</span>         <span class="token punctuation">(</span>exec 模式<span class="token punctuation">)</span>推荐
    CMD <span class="token builtin class-name">command</span> param1 param2                     <span class="token punctuation">(</span>shell模式<span class="token punctuation">)</span>
    CMD <span class="token punctuation">[</span><span class="token string">&quot;param1&quot;</span>,<span class="token string">&quot;param2&quot;</span><span class="token punctuation">]</span>          提供给ENTRYPOINT的默认参数；
<span class="token comment">#解释： </span>
    <span class="token comment">#CMD指定容器启动时默认执行的命令</span>
    <span class="token comment">#每个Dockerfile只能有一条CMD命令，如果指定了多条，只有最后一条会被执行</span>
    <span class="token comment">#如果你在启动容器的时候使用docker run 指定的运行命令，那么会覆盖CMD命令。</span>
    <span class="token comment">#举例： CMD [&quot;/usr/sbin/nginx&quot;,&quot;-g&quot;,&quot;daemon off；&quot;]</span>
    <span class="token string">&quot;/usr/sbin/nginx&quot;</span>   nginx命令
    <span class="token string">&quot;-g&quot;</span>				设置配置文件外的全局指令
    <span class="token string">&quot;daemon off；&quot;</span>		后台守护程序开启方式 关闭
<span class="token comment">#CMD指令实践:</span>
    <span class="token comment">#修改Dockerfile文件内容：</span>
    <span class="token comment">#在上一个Dockerfile文件内容基础上，末尾增加下面一句话：</span>
    CMD <span class="token punctuation">[</span><span class="token string">&quot;/usr/sbin/nginx&quot;</span>,<span class="token string">&quot;-g&quot;</span>,<span class="token string">&quot;daemon off;&quot;</span><span class="token punctuation">]</span>
    <span class="token comment">#构建镜像</span>
    :~/docker/images/nginx$ docker build  -t ubuntu-nginx:v0.3  <span class="token builtin class-name">.</span>
    <span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令</span>
    :~/docker/images/nginx$ docker run --name nginx-1 -itd ubuntu-nginx:v0.3
    <span class="token comment">#根据镜像创建容器,创建时候，添加执行命令/bin/bash</span>
    :~/docker/images/nginx$ docker run  --name nginx-2 -itd ubuntu-nginx:v0.3 /bin/bash
    docker <span class="token function">ps</span>
    
    <span class="token comment">#发现两个容器的命令行是不一样的</span>
    itcast@itcast-virtual-machine:~/docker/images/nginx$ docker <span class="token function">ps</span> -a
    CONTAINER ID  IMAGE             COMMAND                 CREATED           NAMES
    921d00c3689f  ubuntu-nginx:v0.3 <span class="token string">&quot;/bin/bash&quot;</span>             <span class="token number">5</span> seconds ago    nginx-2
    e6c39be8e696  ubuntu-nginx:v0.3 <span class="token string">&quot;/usr/sbin/nginx -g …&quot;</span>  <span class="token number">14</span> seconds ago   nginx-1
    
</code></pre></div><h4 id="entrypoint"><a href="#entrypoint" class="header-anchor">#</a> <strong>ENTRYPOINT</strong></h4> <div class="language-shell extra-class"><pre class="language-shell"><code>ENTRYPOINT
<span class="token comment">#格式：</span>
    ENTRYPOINT <span class="token punctuation">[</span><span class="token string">&quot;executable&quot;</span>, <span class="token string">&quot;param1&quot;</span>,<span class="token string">&quot;param2&quot;</span><span class="token punctuation">]</span> <span class="token punctuation">(</span>exec 模式<span class="token punctuation">)</span>
    ENTRYPOINT <span class="token builtin class-name">command</span> param1 param2 <span class="token punctuation">(</span>shell 模式<span class="token punctuation">)</span>
<span class="token comment">#解释：</span>
    <span class="token comment">#和CMD 类似都是配置容器启动后执行的命令，并且不会被docker run 提供的参数覆盖。</span>
    <span class="token comment">#每个Dockerfile 中只能有一个ENTRYPOINT，当指定多个时，只有最后一个起效。</span>
    <span class="token comment">#生产中我们可以同时使用ENTRYPOINT 和CMD，</span>
    <span class="token comment">#想要在docker run 时被覆盖，可以使用&quot;docker run --entrypoint&quot;</span>
<span class="token comment">#ENTRYPOINT指令实践：</span>
    <span class="token comment">#修改Dockerfile文件内容：</span>
    <span class="token comment">#在上一个Dockerfile 文件内容基础上，修改末尾的CMD 为ENTRYPOINT：</span>
    ENTRYPOINT <span class="token punctuation">[</span><span class="token string">&quot;/usr/sbin/nginx&quot;</span>,<span class="token string">&quot;-g&quot;</span>,<span class="token string">&quot;daemon off;&quot;</span><span class="token punctuation">]</span>
    
    <span class="token comment">#构建镜像</span>
    :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.4 <span class="token builtin class-name">.</span>
    
    <span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令</span>
    :~/docker/images/nginx$ docker run  --name nginx-3 -itd ubuntu-nginx:v0.4
    
    <span class="token comment">#根据镜像创建容器,创建时候，添加执行命令/bin/bash</span>
    :~/docker/images/nginx$ docker run  --name nginx-4 -itd ubuntu-nginx:v0.4 /bin/bash
    
    <span class="token comment">#查看ENTRYPOINT是否被覆盖</span>
    :~/docker/images/nginx$ docker <span class="token function">ps</span> -a
    CONTAINER ID  IMAGE               COMMAND                  CREATED              NAMES
    e7a2f0d0924e  ubuntu-nginx:v0.4   <span class="token string">&quot;/usr/sbin/nginx -g …&quot;</span>   <span class="token number">59</span> seconds ago       nginx-4
    c92b2505e28e  ubuntu-nginx:v0.4   <span class="token string">&quot;/usr/sbin/nginx -g …&quot;</span>   About a minute ago   nginx-3
    
    <span class="token comment">#根据镜像创建容器,创建时候，使用--entrypoint参数，添加执行命令/bin/bash</span>
    docker run  --entrypoint <span class="token string">&quot;/bin/bash&quot;</span> --name nginx-5 -itd ubuntu-nginx:v0.4
    
    <span class="token comment">#查看ENTRYPOINT是否被覆盖</span>
    :~/docker/images/nginx$ docker <span class="token function">ps</span> 
    CONTAINER ID  IMAGE               COMMAND                  CREATED              NAMES
    6c54726b2d96  ubuntu-nginx:v0.4   <span class="token string">&quot;/bin/bash&quot;</span>              <span class="token number">3</span> seconds ago        nginx-5

</code></pre></div><h4 id="cmd-entrypoint-综合使用实践"><a href="#cmd-entrypoint-综合使用实践" class="header-anchor">#</a> <strong>CMD ENTRYPOINT 综合使用实践</strong></h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#修改Dockerfile文件内容：</span>

<span class="token comment"># 在上一个Dockerfile文件内容基础上，修改末尾的ENTRYPOINT</span>

    :~/docker/images/nginx$ <span class="token function">vim</span> Dockerfile
    ENTRYPOINT <span class="token punctuation">[</span><span class="token string">&quot;/usr/sbin/nginx&quot;</span><span class="token punctuation">]</span>
    CMD <span class="token punctuation">[</span><span class="token string">&quot;-g&quot;</span><span class="token punctuation">]</span>
    <span class="token comment">#构建镜像</span>
    :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.5 <span class="token builtin class-name">.</span>
    <span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令</span>
    :~/docker/images/nginx$ docker run --name nginx-6 -d ubuntu-nginx:v0.5
    
    <span class="token comment">#查看效果</span>
   :~/docker/images/nginx$ docker <span class="token function">ps</span> -a 
    CONTAINER ID   IMAGE               COMMAND                  CREATED         NAMES
    e28875d281eb   ubuntu-nginx:v0.5   <span class="token string">&quot;/usr/sbin/nginx -g&quot;</span>     <span class="token number">9</span> seconds ago   nginx-6
<span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令，覆盖cmd的参数 -g &quot;daemon off;&quot;</span>
:~/docker/images/nginx$ docker run  --name nginx-7 -d ubuntu-nginx:v0.5 -g <span class="token string">&quot;daemon off;&quot;</span>

<span class="token comment">#查看效果</span>
itcast@itcast-virtual-machine:~/docker/images/nginx$ docker <span class="token function">ps</span> -a 
CONTAINER ID    IMAGE               COMMAND                  CREATED         NAMES
e5addad86ef5    ubuntu-nginx:v0.5   <span class="token string">&quot;/usr/sbin/nginx -g …&quot;</span>   <span class="token number">5</span> seconds ago   nginx-7
<span class="token comment">#注释：</span>
<span class="token comment">#任何docker run设置的命令参数或者CMD指令的命令，都将作为ENTRYPOINT 指令的命令参数，追加到ENTRYPOINT指令之后</span>
</code></pre></div><h3 id="_3-1-5-文件编辑指令详解"><a href="#_3-1-5-文件编辑指令详解" class="header-anchor">#</a> 3.1.5 文件编辑指令详解</h3> <h4 id="add"><a href="#add" class="header-anchor">#</a> <strong>ADD</strong></h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#ADD</span>
<span class="token comment">#格式：</span>
    ADD <span class="token operator">&lt;</span>src<span class="token operator">&gt;</span><span class="token punctuation">..</span>. <span class="token operator">&lt;</span>dest<span class="token operator">&gt;</span>
    ADD <span class="token punctuation">[</span><span class="token string">&quot;&lt;src&gt;&quot;</span>,<span class="token punctuation">..</span>. <span class="token string">&quot;&lt;dest&gt;&quot;</span><span class="token punctuation">]</span>
<span class="token comment">#解释：</span>
	<span class="token comment"># 将宿主机文件拷贝到容器目录中</span>
  	<span class="token comment"># 如果宿主机文件是可识别的压缩包, 会进行解压缩 -&gt; tar</span>
  	ADD 宿主机文件 容器目录/文件
  	
<span class="token comment">#	ADD [&quot;宿主机文件&quot;, &quot;容器目录&quot;]</span>
   - 宿主机文件一般放到Dockerfile对应的目录中
   - 容器目录, 有可能存在, 有可能不存在
    	- 存在: 直接拷贝到容器目录
      - 不存在: 先在容器中创建一个, 再拷贝
  ADD <span class="token punctuation">[</span><span class="token string">&quot;a.txt&quot;</span>, <span class="token string">&quot;/home/go/a.txt&quot;</span><span class="token punctuation">]</span>
   - 第二个参数如果指定的是一个文件名
     - 这个文件存在: 直接覆盖
     - 不存在: 直接拷贝
<span class="token comment">#ADD实践：</span>
    <span class="token comment">#拷贝普通文件</span>
    :~/docker/images/nginx$ <span class="token function">vim</span> Dockerfile 
    
    <span class="token comment">#Dockerfile文件内容</span>
    
    <span class="token comment"># 构建一个基于ubuntu的docker定制镜像</span>
    <span class="token comment"># 基础镜像</span>
    FROM ubuntu
    <span class="token comment"># 镜像作者</span>
    MAINTAINER panda kstwoak47@163.com
    <span class="token comment"># 执行命令</span>
    ADD <span class="token punctuation">[</span><span class="token string">&quot;sources.list&quot;</span>,<span class="token string">&quot;/etc/apt/sources.list&quot;</span><span class="token punctuation">]</span>
    RUN <span class="token function">apt-get</span> clean
    RUN <span class="token function">apt-get</span> update
    RUN <span class="token function">apt-get</span> <span class="token function">install</span> nginx -y
    <span class="token comment"># 对外端口</span>
    EXPOSE <span class="token number">80</span>
 
    <span class="token comment">#构建镜像</span>
    :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.6 <span class="token builtin class-name">.</span>
    
    <span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令进入容器查看效果</span>
    docker run  --name nginx-8 -it ubuntu-nginx:v0.6
    
    <span class="token comment">#拷贝压缩文件</span>
    <span class="token function">tar</span> zcvf this.tar.gz ./*
    <span class="token comment">#Dockerfile文件内容</span>
    <span class="token punctuation">..</span>.
    <span class="token comment"># 执行命令</span>
    <span class="token punctuation">..</span>.
    <span class="token comment"># 增加文件</span>
    ADD <span class="token punctuation">[</span><span class="token string">&quot;linshi.tar.gz&quot;</span>,<span class="token string">&quot;/nihao/&quot;</span><span class="token punctuation">]</span>
    <span class="token punctuation">..</span>.
    <span class="token comment">#构建镜像</span>
    :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.7 <span class="token builtin class-name">.</span>
    <span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令进入容器查看效果</span>
    docker run --name nginx-9 -it ubuntu-nginx:v0.7
    :~/docker/images/nginx$ docker run --name nginx-9 -it ubuntu-nginx:v0.7
</code></pre></div><h4 id="copy"><a href="#copy" class="header-anchor">#</a> COPY</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#COPY</span>
    <span class="token comment">#格式：</span>
    COPY <span class="token operator">&lt;</span>src<span class="token operator">&gt;</span><span class="token punctuation">..</span>. <span class="token operator">&lt;</span>dest<span class="token operator">&gt;</span>
    COPY <span class="token punctuation">[</span><span class="token string">&quot;&lt;src&gt;&quot;</span>,<span class="token punctuation">..</span>. <span class="token string">&quot;&lt;dest&gt;&quot;</span><span class="token punctuation">]</span>
    <span class="token comment">#解释：</span>
    <span class="token comment">#COPY 指令和ADD 指令功能和使用方式类似。只是COPY 指令不会做自动解压工作。</span>
    <span class="token comment">#单纯复制文件场景，Docker 推荐使用COPY</span>
<span class="token comment">#COPY实践</span>
    <span class="token comment">#修改Dockerfile文件内容:</span>
    <span class="token comment"># 构建一个基于ubuntu的docker定制镜像</span>
    <span class="token comment"># 基础镜像</span>
    FROM ubuntu
    <span class="token comment"># 镜像作者</span>
    MAINTAINER panda kstwoak47@163.com
    <span class="token comment"># 执行命令</span>
ADD <span class="token punctuation">[</span><span class="token string">&quot;sources.list&quot;</span>,<span class="token string">&quot;/etc/apt/sources.list&quot;</span><span class="token punctuation">]</span>
RUN <span class="token function">apt-get</span> clean
RUN <span class="token function">apt-get</span> update
RUN <span class="token function">apt-get</span> <span class="token function">install</span> nginx -y
COPY <span class="token punctuation">[</span><span class="token string">&quot;index.html&quot;</span>,<span class="token string">&quot;/var/www/html/&quot;</span><span class="token punctuation">]</span>
<span class="token comment"># 对外端口</span>
EXPOSE <span class="token number">80</span>
<span class="token comment">#运行时默认命令 </span>
ENTRYPOINT <span class="token punctuation">[</span><span class="token string">&quot;/usr/sbin/nginx&quot;</span>,<span class="token string">&quot;-g&quot;</span>,<span class="token string">&quot;daemon off;&quot;</span><span class="token punctuation">]</span>
index.html 文件内容：
<span class="token operator">&lt;</span>h<span class="token operator"><span class="token file-descriptor important">1</span>&gt;</span>hello world <span class="token operator">&lt;</span>/h<span class="token operator"><span class="token file-descriptor important">1</span>&gt;</span>
<span class="token operator">&lt;</span>h<span class="token operator"><span class="token file-descriptor important">1</span>&gt;</span>hello docker <span class="token operator">&lt;</span>/h<span class="token operator"><span class="token file-descriptor important">1</span>&gt;</span>
<span class="token operator">&lt;</span>h<span class="token operator"><span class="token file-descriptor important">1</span>&gt;</span>hello nginx<span class="token operator">&lt;</span>/h<span class="token operator"><span class="token file-descriptor important">1</span>&gt;</span>
 
<span class="token comment">#构建镜像</span>
:~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.8 <span class="token builtin class-name">.</span>
<span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令</span>
:~/docker/images/nginx$ docker run  --name nginx-10 -itd ubuntu-nginx:v0.8
<span class="token comment">#查看nginx-10信息</span>
:~/docker/images/nginx<span class="token variable">$docker</span> inspect  nginx-10
<span class="token comment">#浏览器访问nginx查看效果    </span>
</code></pre></div><p><strong>VOLUME</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#VOLUME</span>
    <span class="token comment">#格式：</span>
    VOLUME <span class="token punctuation">[</span><span class="token string">&quot;/data&quot;</span><span class="token punctuation">]</span>
    <span class="token comment">#解释：</span>
    <span class="token comment">#VOLUME 指令可以在镜像中创建挂载点，这样只要通过该镜像创建的容器都有了挂载点</span>
    <span class="token comment">#通过VOLUME 指令创建的挂载点，无法指定主机上对应的目录，是自动生成的。</span>
    <span class="token comment">#举例：</span>
    VOLUME <span class="token punctuation">[</span><span class="token string">&quot;/var/lib/tomcat7/webapps/&quot;</span><span class="token punctuation">]</span>
</code></pre></div><p><strong>VOLUME实践</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#VOLUME实践</span>
<span class="token comment">#修改Dockerfile文件内容：</span>
<span class="token comment">#将COPY替换成为VOLUME</span>
:~/docker/images/nginx<span class="token variable">$vim</span> Dockerfile
VOLUME <span class="token punctuation">[</span><span class="token string">&quot;/helloworld/&quot;</span><span class="token punctuation">]</span>
<span class="token punctuation">..</span>.
<span class="token comment">#构建镜像</span>
:~/docker/images/nginx<span class="token variable">$docker</span> build -t ubuntu-nginx:v0.9 <span class="token builtin class-name">.</span>
<span class="token comment">#创建数据卷容器</span>
:~/docker/images/nginx<span class="token variable">$docker</span> run -itd --name nginx-11 ubuntu-nginx:v0.9
<span class="token comment">#查看镜像信息</span>
:~/docker/images/nginx<span class="token variable">$docker</span> inspect nginx-11
<span class="token comment">#验证操作</span>
:~/docker/images/nginx<span class="token variable">$docker</span> run -itd --name vc-nginx-1 --volumes-from nginx-11 nginx
:~/docker/images/nginx<span class="token variable">$docker</span> run -itd --name vc-nginx-2 --volumes-from nginx-11 nginx
<span class="token comment">#进入容器1</span>
:~/docker/images/nginx<span class="token variable">$docker</span> <span class="token builtin class-name">exec</span> -it vc-nginx-1 /bin/bash
:/<span class="token comment"># echo 'nihao itcast' &gt; helloworld/nihao.txt</span>
<span class="token comment">#进入容器2</span>
:~/docker/images/nginx$ docker <span class="token builtin class-name">exec</span> -it vc-nginx-2 /bin/bash
:/<span class="token comment"># cat helloworld/nihao.txt</span>
</code></pre></div><h3 id="_3-1-6-环境指令详解"><a href="#_3-1-6-环境指令详解" class="header-anchor">#</a> 3.1.6 环境指令详解</h3> <h4 id="env"><a href="#env" class="header-anchor">#</a> ENV</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#ENV</span>
    <span class="token comment">#格式：</span>
    ENV <span class="token operator">&lt;</span>key<span class="token operator">&gt;</span> <span class="token operator">&lt;</span>value<span class="token operator">&gt;</span>                    （一次设置一个环节变量）
    ENV <span class="token operator">&lt;</span>key<span class="token operator">&gt;</span><span class="token operator">=</span><span class="token operator">&lt;</span>value<span class="token operator">&gt;</span> <span class="token punctuation">..</span>.                （一次设置一个或多个环节变量）
    ENV HELLO <span class="token number">12345</span>
  	ENV <span class="token assign-left variable">HELLO</span><span class="token operator">=</span><span class="token number">12345</span>
  	ENV <span class="token assign-left variable">HELLO</span><span class="token operator">=</span><span class="token number">12345</span> <span class="token assign-left variable">WORLD</span><span class="token operator">=</span><span class="token number">12345</span> <span class="token assign-left variable">NIHAO</span><span class="token operator">=</span><span class="token number">12345</span>
<span class="token comment">#解释：</span>
<span class="token comment">#设置环境变量，可以在RUN 之前使用，然后RUN 命令时调用，容器启动时这些环境变量都会被指定</span>
</code></pre></div><p><strong>ENV实践</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#ENV实践：</span>
    <span class="token comment">#命令行创建ENV的容器</span>
    :~$ docker run -e <span class="token assign-left variable">NIHAO</span><span class="token operator">=</span><span class="token string">&quot;helloworld&quot;</span> -itd --name ubuntu-111 ubuntu /bin/bash
    <span class="token comment">#进入容器ubuntu-111</span>
    :~$ docker <span class="token builtin class-name">exec</span> -it ubuntu-111 /bin/bash
    :/<span class="token comment"># echo $NIHAO</span>
    
    <span class="token comment">#修改Dockerfile文件内容：</span>
    <span class="token comment">#在上一个Dockerfile 文件内容基础上，在RUN 下面增加一个ENV</span>
    ENV <span class="token assign-left variable">NIHAO</span><span class="token operator">=</span>helloworld
    <span class="token punctuation">..</span>.
    <span class="token comment">#构建镜像</span>
    docker build -t ubuntu-nginx:v0.10 <span class="token builtin class-name">.</span>
    
    <span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令</span>
    docker run  --name nginx-12 -itd ubuntu-nginx:v0.10
    docker <span class="token builtin class-name">exec</span> -it nginx-12 /bin/bash
    <span class="token builtin class-name">echo</span> <span class="token variable">$NIHAO</span>
</code></pre></div><h4 id="workdir"><a href="#workdir" class="header-anchor">#</a> WORKDIR</h4> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#WORKDIR</span>
    <span class="token comment">#格式：</span>
    WORKDIR /path/to/workdir <span class="token punctuation">(</span>shell 模式<span class="token punctuation">)</span>
    <span class="token comment">#解释：</span>
    <span class="token comment">#切换目录，为后续的RUN、CMD、ENTRYPOINT 指令配置工作目录。相当于cd</span>
    <span class="token comment">#可以多次切换(相当于cd 命令)，</span>
    <span class="token comment">#也可以使用多个WORKDIR 指令，后续命令如果参数是相对路径，则会基于之前命令指定的路径。例如</span>
    <span class="token comment">#举例：</span>
    WORKDIR /a
    WORKDIR b
    WORKDIR c
    RUN <span class="token builtin class-name">pwd</span>
    <span class="token comment">#则最终路径为/a/b/c</span>
</code></pre></div><p><strong>WORKDIR实践</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#WORKDIR实践：</span>
    <span class="token comment">#修改Dockerfile文件内容：</span>
    <span class="token comment"># 在上一个Dockerfile 文件内容基础上，在RUN 下面增加一个WORKDIR</span>
    WORKDIR /nihao/itcast/
    RUN <span class="token punctuation">[</span><span class="token string">&quot;touch&quot;</span>,<span class="token string">&quot;itcast1.txt&quot;</span><span class="token punctuation">]</span>
    WORKDIR /nihao
    RUN <span class="token punctuation">[</span><span class="token string">&quot;touch&quot;</span>,<span class="token string">&quot;itcast2.txt&quot;</span><span class="token punctuation">]</span>
    WORKDIR itcast
    RUN <span class="token punctuation">[</span><span class="token string">&quot;touch&quot;</span>,<span class="token string">&quot;itcast3.txt&quot;</span><span class="token punctuation">]</span>
    <span class="token punctuation">..</span>.
    <span class="token comment">#构建镜像</span>
    :~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.11 <span class="token builtin class-name">.</span>
    <span class="token comment">#根据镜像创建容器,创建时候，不添加执行命令</span>
    docker run  --name nginx-13 -itd ubuntu-nginx:v0.11
    <span class="token comment">#进入镜像</span>
    docker <span class="token builtin class-name">exec</span> -it nginx-13 /bin/bash
</code></pre></div><p><strong>USER与ARG</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code>
<span class="token comment">#USER</span>
    <span class="token comment">#格式：</span>
    <span class="token environment constant">USER</span> daemon
    <span class="token comment">#解释：</span>
    <span class="token comment">#指定运行容器时的用户名和UID，后续的RUN 指令也会使用这里指定的用户。</span>
    <span class="token comment">#如果不输入任何信息，表示默认使用root 用户</span>

<span class="token comment">#ARG</span>
    <span class="token comment">#格式：</span>
    ARG <span class="token operator">&lt;</span>name<span class="token operator">&gt;</span><span class="token punctuation">[</span><span class="token operator">=</span><span class="token operator">&lt;</span>default value<span class="token operator">&gt;</span><span class="token punctuation">]</span>
    <span class="token comment">#解释：</span>
    <span class="token comment">#ARG 指定了一个变量在docker build 的时候使用，可以使用--build-arg &lt;varname&gt;=&lt;value&gt;来指定参数的值，不过</span>
    <span class="token comment">#如果构建的时候不指定就会报错。</span>

</code></pre></div><h3 id="_3-1-7-触发器指令详解"><a href="#_3-1-7-触发器指令详解" class="header-anchor">#</a> 3.1.7 触发器指令详解</h3> <p>触发器指令</p> <div class="language-shell extra-class"><pre class="language-shell"><code>ONBUILD
<span class="token comment">#格式：</span>
    ONBUILD <span class="token punctuation">[</span>command<span class="token punctuation">]</span>
<span class="token comment">#解释：</span>
    <span class="token comment">#当一个镜像A被作为其他镜像B的基础镜像时，这个触发器才会被执行，</span>
    <span class="token comment">#新镜像B在构建的时候，会插入触发器中的指令。</span>
    <span class="token comment">#使用场景对于版本控制和方便传输，适用于其他用户。</span>
    
  <span class="token comment"># 原始镜像 -&gt; 纯净版</span>
  	-<span class="token operator">&gt;</span> 修改 ONBUILD <span class="token punctuation">[</span><span class="token string">&quot;echo&quot;</span>, <span class="token string">&quot;hello,linux&quot;</span><span class="token punctuation">]</span>
  	   
  <span class="token comment"># 基于原始镜像制作新镜像 -&gt; 镜像A</span>
  	-<span class="token operator">&gt;</span> 启动镜像A -<span class="token operator">&gt;</span> 不会输出hello, linux
  	
  <span class="token comment"># 基于镜像A制作了镜像B</span>
  	-<span class="token operator">&gt;</span> 启动镜像B -<span class="token operator">&gt;</span> 会输出 hello, linux
</code></pre></div><p>触发器实践</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#编辑Dockerfile</span>
:~/docker/images/nginx$ <span class="token function">vim</span> Dockerfile 
<span class="token comment">#内容如下：</span>
<span class="token comment"># 构建一个基于ubuntu的docker定制镜像</span>
<span class="token comment"># 基础镜像</span>
FROM ubuntu
<span class="token comment"># 镜像作者</span>
MAINTAINER panda kstwoak47@163.com
<span class="token comment"># 执行命令</span>
ADD <span class="token punctuation">[</span><span class="token string">&quot;sources.list&quot;</span>,<span class="token string">&quot;/etc/apt/sources.list&quot;</span><span class="token punctuation">]</span> 
RUN <span class="token function">apt-get</span> clean
RUN <span class="token function">apt-get</span> update 
RUN <span class="token function">apt-get</span> <span class="token function">install</span> nginx -y 
<span class="token comment">#触发器</span>
ONBUILD COPY <span class="token punctuation">[</span><span class="token string">&quot;index.html&quot;</span>,<span class="token string">&quot;/var/www/html/&quot;</span><span class="token punctuation">]</span>
<span class="token comment"># 对外端口</span>
EXPOSE <span class="token number">80</span>
<span class="token comment">#运行时默认命令 </span>
ENTRYPOINT <span class="token punctuation">[</span><span class="token string">&quot;/usr/sbin/nginx&quot;</span>,<span class="token string">&quot;-g&quot;</span>,<span class="token string">&quot;daemon off;&quot;</span><span class="token punctuation">]</span>
 
<span class="token comment">#构建镜像</span>
:~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.12 <span class="token builtin class-name">.</span>
 
<span class="token comment">#根据镜像创建容器,</span>
:~/docker/images/nginx<span class="token variable">$docker</span> run -p <span class="token number">80</span> --name nginx-14 -itd ubuntu-nginx:v0.12
:~/docker/images/nginx<span class="token variable">$docker</span> <span class="token function">ps</span>
<span class="token comment">#查看镜像信息</span>
:~/docker/images/nginx$ docker inspect ubuntu-nginx:v0.12  
<span class="token comment">#访问容器页面，是否被更改</span>
:~/docker/images/nginx$ docker inspect nginx-14

</code></pre></div><div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#构建子镜像Dockerfile文件</span>
FROM ubuntu-nginx:v0.12
MAINTAINER panda kstwoak47@163.com
EXPOSE <span class="token number">80</span>
ENTRYPOINT <span class="token punctuation">[</span><span class="token string">&quot;/usr/sbin/nginx&quot;</span>,<span class="token string">&quot;-g&quot;</span>,<span class="token string">&quot;daemon off;&quot;</span><span class="token punctuation">]</span>
 
<span class="token comment">#构建子镜像</span>
:~/docker/images/nginx$ docker build -t ubuntu-nginx:v0.13 <span class="token builtin class-name">.</span>
<span class="token comment">#根据镜像创建容器,</span>
docker run -p <span class="token number">80</span> --name nginx-15 -itd ubuntu-nginx:v0.13
<span class="token comment">#查看镜像信息</span>
:~/docker/images/nginx$ docker inspect ubuntu-nginx:v0.13
docker <span class="token function">ps</span>
<span class="token comment">#访问容器页面，是否被更改</span>

</code></pre></div><h3 id="_3-1-8-dockerfile构建缓存"><a href="#_3-1-8-dockerfile构建缓存" class="header-anchor">#</a> 3.1.8 Dockerfile构建缓存</h3> <p>我们第一次构建很慢，之后的构建都会很快，因为他们用到了构建的缓存。</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#取消缓存：</span>
docker build --no-cache -t <span class="token punctuation">[</span>镜像名<span class="token punctuation">]</span>:<span class="token punctuation">[</span>镜像版本<span class="token punctuation">]</span><span class="token punctuation">[</span>Dockerfile位置<span class="token punctuation">]</span>
</code></pre></div><h2 id="_3-2-dockerfile构建go环境"><a href="#_3-2-dockerfile构建go环境" class="header-anchor">#</a> 3.2 Dockerfile构建go环境</h2> <p>接下来我们就来做一个工作实践，搭建一个go环境,然后尝试使用Dockerfile的方式，构造一个镜像。</p> <h3 id="_3-2-1-项目描述"><a href="#_3-2-1-项目描述" class="header-anchor">#</a> 3.2.1 项目描述</h3> <p>beego官方网站：https://beego.me/</p> <p>我们借助于beego的简介，部署一个go项目，然后运行起来。</p> <h3 id="_3-2-2-手工部署go语言环境"><a href="#_3-2-2-手工部署go语言环境" class="header-anchor">#</a> 3.2.2 手工部署go语言环境</h3> <p><strong>需求：</strong></p> <p>基于docker镜像，手工部署go项目环境</p> <p><strong>方案分析：</strong></p> <p>1、docker环境部署</p> <p>2、go环境部署</p> <p>3、go项目部署</p> <p>4、测试</p> <p>技术关键点：</p> <p>1、docker环境部署</p> <p>使用docker镜像启动一个容器即可</p> <p>2、go环境部署</p> <p>go软件的依赖环境</p> <p>go软件的基本环境配置</p> <p>3、go项目部署</p> <p>beego框架的下载</p> <p>项目文件配置</p> <p>启动go项目</p> <p>4、测试</p> <p>宿主机测试</p> <p>解决方案：</p> <p>1、docker环境配置</p> <p>1.1 获取docker镜像</p> <p>1.2 启动docker容器</p> <p>2、go环境部署</p> <p>2.1 基础环境配置</p> <p>2.2 go环境配置</p> <p>3、go项目部署</p> <p>3.1 获取beego代码</p> <p>3.2 项目文件配置</p> <p>3.3 项目启动</p> <p>4、测试</p> <p>4.1 宿主机测试</p> <p><strong>实施方案：</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#1、docker环境配置</span>
<span class="token comment">#1.1 获取docker镜像</span>
<span class="token comment">#获取一个ubuntu的模板文件</span>
<span class="token function">cat</span> ubuntu-16.04-x86_64.tar.gz <span class="token operator">|</span> docker <span class="token function">import</span> - ubuntu-nimi
<span class="token comment">#1.2 启动docker容器</span>
<span class="token comment">#启动容器，容器名称叫go-test</span>
docker run -itd --name go-test ubuntu-nimi
<span class="token comment">#进入容器</span>
docker <span class="token builtin class-name">exec</span> -it go-test /bin/bash
<span class="token comment">#2、go环境部署</span>
<span class="token comment">#2.1 基础环境配置</span>
<span class="token comment">#配置国内源</span>
<span class="token function">vim</span> /etc/apt/sources.list
<span class="token comment">#文件内容如下</span>
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse
<span class="token comment">#如果由于网络环境原因不能进行软件源更新可以使用如下内容</span>
<span class="token function">sudo</span> <span class="token function">sed</span> -i <span class="token string">'s/cn.archive.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list 

<span class="token comment">#更新软件源，安装基本软件</span>
<span class="token function">apt-get</span> update
<span class="token function">apt-get</span> <span class="token function">install</span> gcc libc6-dev <span class="token function">git</span> <span class="token function">vim</span> lrzsz -y
<span class="token comment">#2.2 go环境配置</span>
<span class="token comment">#安装go语言软件</span>
//apt-get <span class="token function">install</span> golang -y
由于软件源问题改使用新版本go
将go1.10.linux-amd64.tar.gz拷贝到容器中进行解压
<span class="token function">tar</span> -C /usr/local  -zxf go1.10.linux-amd64.tar.gz

<span class="token comment">#配置go基本环境变量</span>
<span class="token builtin class-name">export</span> <span class="token assign-left variable">GOROOT</span><span class="token operator">=</span>/usr/local/go                
<span class="token builtin class-name">export</span> <span class="token assign-left variable"><span class="token environment constant">PATH</span></span><span class="token operator">=</span><span class="token environment constant">$PATH</span>:/usr/local/go/bin   
<span class="token builtin class-name">export</span> <span class="token assign-left variable">GOPATH</span><span class="token operator">=</span>/root/go
<span class="token builtin class-name">export</span> <span class="token assign-left variable"><span class="token environment constant">PATH</span></span><span class="token operator">=</span><span class="token variable">$GOPATH</span>/bin/:<span class="token environment constant">$PATH</span>
<span class="token comment">#3、go项目部署</span>
<span class="token comment">#3.1 获取beego代码</span>
<span class="token comment">#下载项目beego</span>
go get github.com/astaxie/beego
<span class="token comment">#3.2 项目文件配置</span>
<span class="token comment">#创建项目目录</span>
<span class="token function">mkdir</span> /root/go/src/myTest
<span class="token builtin class-name">cd</span> /root/go/src/myTest
<span class="token comment">#编辑go项目测试文件test.go</span>
package main
<span class="token function">import</span> <span class="token punctuation">(</span>
<span class="token string">&quot;github.com/astaxie/beego&quot;</span>
<span class="token punctuation">)</span>
<span class="token builtin class-name">type</span> MainController struct <span class="token punctuation">{</span>
beego.Controller
<span class="token punctuation">}</span>
func <span class="token punctuation">(</span>this *MainController<span class="token punctuation">)</span> <span class="token function-name function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
this.Ctx.WriteString<span class="token punctuation">(</span><span class="token string">&quot;hello world<span class="token entity" title="\n">\n</span>&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
func <span class="token function-name function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
beego.Router<span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span>, <span class="token operator">&amp;</span>MainController<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
beego.Run<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token comment">#3.3 项目启动</span>
<span class="token comment">#运行该文件</span>
go run test.go
<span class="token comment">#可以看到：</span>
<span class="token comment">#这个go项目运行起来后，开放的端口是8080</span>
<span class="token comment">#4、测试</span>
<span class="token comment">#4.1宿主机测试</span>
<span class="token comment">#查看容器的ip地址</span>
docker inspect go-test
<span class="token comment">#浏览器查看效果：</span>
<span class="token function">curl</span> <span class="token number">172.17</span>.0.2:8080
</code></pre></div><h3 id="_3-2-3-dockerfile案例分析"><a href="#_3-2-3-dockerfile案例分析" class="header-anchor">#</a> 3.2.3 Dockerfile案例分析</h3> <p>环境分析：</p> <p>1、软件源文件，使用国外源，速度太慢，所以我们可以自己使用国内的软件源。</p> <p>因为我们在手工部署的时候，使用的是官方(国外)的源，所以为了部署快一点呢，我使用国内的阿里云的源。
源内容：</p> <div class="language-shell extra-class"><pre class="language-shell"><code>deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse
</code></pre></div><p>由于阿里云的源出现问题所有更换为中科大的源 详情见3.1.1</p> <p>2、软件安装，涉及到了各种软件</p> <p>3、涉及到了go的环境变量设置</p> <p>4、软件运行涉及到了软件的运行目录</p> <p>5、项目访问，涉及到端口</p> <p>关键点分析：</p> <p>1、增加文件，使用 ADD 或者 COPY 指令</p> <p>2、安装软件，使用 RUN 指令</p> <p>3、环境变量，使用 ENV 指令</p> <p>4、命令运行，使用 WORKDIR 指令</p> <p>5、项目端口，使用 EXPOSE 指令</p> <p>定制方案：</p> <p>1、基于ubuntu基础镜像进行操作</p> <p>2、增加国内源文件</p> <p>3、安装环境基本软件</p> <p>4、定制命令工作目录</p> <p>5、执行项目</p> <p>6、开放端口</p> <h3 id="_3-2-4-dockerfile实践"><a href="#_3-2-4-dockerfile实践" class="header-anchor">#</a> 3.2.4 Dockerfile实践</h3> <p><strong>创建目录</strong></p> <div class="language- extra-class"><pre class="language-text"><code>#创建目录
#进入标准目录
mkdir /docker/images/beego
cd /docker/images/beego
</code></pre></div><p><strong>Dockerfile内容</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment"># 构建一个基于ubuntu 的docker 定制镜像</span>
<span class="token comment"># 基础镜像</span>
FROM ubuntu

<span class="token comment"># 镜像作者</span>
MAINTAINER panda kstwoak47@163.com

<span class="token comment"># 增加国内源</span>
<span class="token comment">#COPY sources.list /etc/apt/</span>

RUN <span class="token function">sed</span> -i <span class="token string">'s/archive.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list
RUN <span class="token function">sed</span> -i <span class="token string">'s/security.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list

<span class="token comment"># 执行命令</span>

RUN <span class="token function">apt-get</span> update
RUN <span class="token function">apt-get</span> <span class="token function">install</span> gcc libc6-dev <span class="token function">git</span> lrzsz -y
<span class="token comment">#将go复制解压到容器中</span>
ADD go1.10.linux-amd64.tar.gz  /usr/local/

<span class="token comment"># 定制环境变量</span>

ENV <span class="token assign-left variable">GOROOT</span><span class="token operator">=</span>/usr/local/go                
ENV <span class="token assign-left variable"><span class="token environment constant">PATH</span></span><span class="token operator">=</span><span class="token environment constant">$PATH</span>:/usr/local/go/bin   
ENV <span class="token assign-left variable">GOPATH</span><span class="token operator">=</span>/root/go
ENV <span class="token assign-left variable"><span class="token environment constant">PATH</span></span><span class="token operator">=</span><span class="token variable">$GOPATH</span>/bin/:<span class="token environment constant">$PATH</span>

<span class="token comment"># 下载项目</span>

RUN go get github.com/astaxie/beego

<span class="token comment"># 增加文件</span>

COPY test.go /root/go/src/myTest/

<span class="token comment"># 定制工作目录</span>

WORKDIR /root/go/src/myTest/

<span class="token comment"># 对外端口</span>

EXPOSE <span class="token number">8080</span>

<span class="token comment"># 运行项目</span>

ENTRYPOINT <span class="token punctuation">[</span><span class="token string">&quot;go&quot;</span>,<span class="token string">&quot;run&quot;</span>,<span class="token string">&quot;test.go&quot;</span><span class="token punctuation">]</span>

<span class="token comment">#把sources.list和test.go文件放到这个目录中</span>
<span class="token comment">#构建镜像</span>
docker build -t go-test:v0.1 <span class="token builtin class-name">.</span>
<span class="token comment">#运行镜像</span>
docker run -p <span class="token number">8080</span>:8080 -itd go-test:v0.1
<span class="token comment">#访问镜像，查看效果</span>
</code></pre></div><h2 id="_3-3-docker-compose"><a href="#_3-3-docker-compose" class="header-anchor">#</a> 3.3 Docker compose</h2> <p>Docker compose是一种docker容器的任务编排工具</p> <p>官方地址：https://docs.docker.com/compose/</p> <h3 id="_3-3-1-compose简介"><a href="#_3-3-1-compose简介" class="header-anchor">#</a> 3.3.1 compose简介</h3> <p>任务编排介绍</p> <p>场景：</p> <p>​       我们在工作中为了完成业务目标，首先把业务拆分成多个子任务，然后对这些子任务进行顺序组合，当子任务按照方案执行完毕后，就完成了业务目标。</p> <p>​       任务编排，就是对多个子任务执行顺序进行确定的过程。</p> <p>常见的任务编排工具：</p> <p>单机版：   docker compose</p> <p>集群版：</p> <p>Docker swarm               Docker</p> <p>Mesos                 		Apache</p> <p>Kubernetes（k8s）       Google</p> <p><strong>docker compose是什么</strong></p> <p><img src="assets/1541810582833.png" alt="1541810582833"></p> <p><strong>译文：</strong>
compose是定义和运行多容器Docker应用程序的工具。通过编写，您可以使用YAML文件来配置应用程序的服务。然后，使用单个命令创建并启动配置中的所有服务。要了解更多有关组合的所有特性，请参见特性列表。</p> <p><strong>docker compose的特点；</strong>
本质：docker 工具</p> <p>对象：应用服务</p> <p>配置：YAML 格式配置文件</p> <p>命令：简单</p> <p>执行：定义和运行容器</p> <p><strong>docker compose的配置文件</strong></p> <p>docker-compose.yml</p> <p>文件后缀是yml</p> <p>文件内容遵循 ymal格式</p> <h3 id="docker-和-docker-compose"><a href="#docker-和-docker-compose" class="header-anchor">#</a> docker 和 Docker compose</h3> <table><thead><tr><th><strong>Compose file format</strong></th> <th><strong>Docker Engine release</strong></th> <th></th> <th><strong>Compose file format</strong></th> <th><strong>Docker Engine release</strong></th></tr></thead> <tbody><tr><td>3.4</td> <td>17.09.0+</td> <td></td> <td>2.3</td> <td>17.06.0+</td></tr> <tr><td>3.3</td> <td>17.06.0+</td> <td></td> <td>2.2</td> <td>1.13.0+</td></tr> <tr><td>3.2</td> <td>17.04.0+</td> <td></td> <td>2.1</td> <td>1.12.0+</td></tr> <tr><td>3.1</td> <td>1.13.1+</td> <td></td> <td>2.0</td> <td>1.10.0+</td></tr> <tr><td>3.0</td> <td>1.13.0+</td> <td></td> <td>1.0</td> <td>1.9.1.+</td></tr></tbody></table> <p>官方地址：https://docs.docker.com/compose/overview/</p> <h3 id="_3-3-2-compose-快速入门"><a href="#_3-3-2-compose-快速入门" class="header-anchor">#</a> 3.3.2 compose 快速入门</h3> <p><strong>docker compose 安装</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#安装依赖工具</span>
<span class="token function">sudo</span> <span class="token function">apt-get</span> <span class="token function">install</span> python-pip -y
<span class="token comment">#安装编排工具</span>
<span class="token function">sudo</span> pip <span class="token function">install</span> docker-compose
<span class="token comment">#查看编排工具版本</span>
<span class="token function">sudo</span> docker-compose version
<span class="token comment">#查看命令帮助</span>
docker-compose --help
</code></pre></div><p><strong>PIP 源问题</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#用pip安装依赖包时默认访问https://pypi.python.org/simple/，</span>
<span class="token comment">#但是经常出现不稳定以及访问速度非常慢的情况，国内厂商提供的pipy镜像目前可用的有：</span>

<span class="token comment">#在当前用户目录下创建.pip文件夹</span>
<span class="token function">mkdir</span> ~/.pip
<span class="token comment">#然后在该目录下创建pip.conf文件填写：</span>
<span class="token punctuation">[</span>global<span class="token punctuation">]</span>
trusted-host<span class="token operator">=</span>mirrors.aliyun.com
index-url<span class="token operator">=</span>http://mirrors.aliyun.com/pypi/simple/
</code></pre></div><p><strong>compose简单配置文件</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#创建compose文件夹</span>
:~$ <span class="token function">mkdir</span> -p ./docker/compose
<span class="token comment">#进入到文件夹</span>
:~$ <span class="token builtin class-name">cd</span> ./docker/compose
<span class="token comment">#创建yml文件</span>
:~$ <span class="token function">vim</span> docker-compose.yml
</code></pre></div><p><strong>docker-compose.yml 文件内容</strong></p> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">'2'</span>
<span class="token key atrule">services</span><span class="token punctuation">:</span>
  <span class="token key atrule">web1</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">&quot;9999:80&quot;</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>web1
  <span class="token key atrule">web2</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">&quot;8888:80&quot;</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>web2
</code></pre></div><p><strong>运行一个容器</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#后台启动：</span>
docker-compose up -d
<span class="token comment">#注意：</span>
    <span class="token comment">#如果不加-d，那么界面就会卡在前台</span>
<span class="token comment">#查看运行效果</span>
docker-compose <span class="token function">ps</span>
</code></pre></div><h3 id="_3-3-3-compose命令详解"><a href="#_3-3-3-compose命令详解" class="header-anchor">#</a> 3.3.3 compose命令详解</h3> <p><strong>注意：</strong></p> <p>所有命令尽量都在docker compose项目目录下面进行操作</p> <p>项目目录：docker-compose.yml所在目录</p> <p><strong>compose服务启动、关闭、查看</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#后台启动：</span>
docker-compose up -d
<span class="token comment">#删除服务</span>
docker-compose down
<span class="token comment">#查看正在运行的服务</span>
docker-compose <span class="token function">ps</span>
</code></pre></div><p><strong>容器开启、关闭、删除</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#启动一个服务</span>
docker-compose start <span class="token operator">&lt;</span>服务名<span class="token operator">&gt;</span>
<span class="token comment">#注意：</span>
    <span class="token comment">#如果后面不加服务名，会停止所有的服务</span>
<span class="token comment">#停止一个服务</span>
docker-compose stop <span class="token operator">&lt;</span>服务名<span class="token operator">&gt;</span>
<span class="token comment">#注意：</span>
    <span class="token comment">#如果后面不加服务名，会停止所有的服务</span>
<span class="token comment">#删除服务</span>
docker-compose <span class="token function">rm</span>
<span class="token comment">#注意：</span>
    <span class="token comment">#这个docker-compose rm不会删除应用的网络和数据卷。工作中尽量不要用rm进行删除</span>
</code></pre></div><p><strong>其他信息查看</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#查看运行的服务</span>
docker-compose <span class="token function">ps</span>
<span class="token comment">#查看服务运行的日志</span>
docker-compose logs -f
<span class="token comment">#注意：</span>
    <span class="token comment">#加上-f 选项，可以持续跟踪服务产生的日志</span>
<span class="token comment">#查看服务依赖的镜像</span>
docke-compose  images
<span class="token comment">#进入服务容器</span>
docker-compose <span class="token builtin class-name">exec</span> <span class="token operator">&lt;</span>服务名<span class="token operator">&gt;</span> <span class="token operator">&lt;</span>执行命令<span class="token operator">&gt;</span>
<span class="token comment">#查看服务网络</span>
docker network <span class="token function">ls</span>
</code></pre></div><h3 id="_3-3-4-compose文件详解"><a href="#_3-3-4-compose文件详解" class="header-anchor">#</a> 3.3.4 compose文件详解</h3> <p>官方参考资料：
https://docs.docker.com/compose/overview/</p> <p><strong>文件命名：</strong></p> <p>后缀是 .yml</p> <h3 id="_2-2-yaml文件格式"><a href="#_2-2-yaml文件格式" class="header-anchor">#</a> 2.2 yaml文件格式</h3> <blockquote><ul><li><p>YAML有以下基本规则：
1、大小写敏感
2、使用缩进表示层级关系
3、禁止使用tab缩进，只能使用空格键
4、缩进长度没有限制，只要元素对齐就表示这些元素属于一个层级。
5、使用#表示注释
6、字符串可以不用引号标注</p> <p>​     	&quot;我是字符串&quot;</p> <p>​	'我是字符串'</p> <p>​       我是字符串</p></li></ul></blockquote> <p>yaml中的三种数据结构</p> <ul><li><p>map - 散列表</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code><span class="token comment"># 使用冒号（：）表示键值对，同一缩进的所有键值对属于一个map，示例：</span>
<span class="token key atrule">age</span> <span class="token punctuation">:</span> <span class="token number">12</span>
<span class="token key atrule">name</span> <span class="token punctuation">:</span> huang
<span class="token comment"># 也可以这样写</span>
<span class="token punctuation">{</span>age<span class="token punctuation">:</span><span class="token number">12</span><span class="token punctuation">,</span> name<span class="token punctuation">:</span>huang<span class="token punctuation">}</span>
 
<span class="token comment"># 使用json</span>
<span class="token punctuation">{</span>&quot;age&quot;<span class="token punctuation">:</span><span class="token number">12</span><span class="token punctuation">,</span> &quot;name&quot;<span class="token punctuation">:</span><span class="token string">&quot;huang&quot;</span><span class="token punctuation">}</span>
</code></pre></div></li> <li><p>list - 数组</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code><span class="token comment"># 使用连字符（-）表示：</span>
<span class="token comment"># YAML表示</span>
<span class="token punctuation">-</span> a
<span class="token punctuation">-</span> b
<span class="token punctuation">-</span> <span class="token number">12</span>
<span class="token punctuation">[</span>a<span class="token punctuation">,</span> b<span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">]</span>

<span class="token comment"># 使用json表示</span>
<span class="token punctuation">[</span><span class="token string">&quot;a&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;b&quot;</span><span class="token punctuation">,</span> <span class="token number">12</span><span class="token punctuation">]</span>
</code></pre></div></li> <li><p>scalar - 纯量</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code>字符串
 <span class="token punctuation">-</span> <span class="token string">&quot;wos字符串&quot;</span>
 <span class="token punctuation">-</span> 我是字符串
布尔值
  <span class="token punctuation">-</span> <span class="token boolean important">true</span>
  <span class="token punctuation">-</span> <span class="token boolean important">false</span>
整数
浮点数
NULL 
 <span class="token punctuation">-</span> 使用 ~ 表示
</code></pre></div></li> <li><p>例子</p> <div class="language-yaml extra-class"><pre class="language-yaml"><code><span class="token comment"># 1</span>
<span class="token key atrule">Websites</span><span class="token punctuation">:</span>
 <span class="token key atrule">YAML</span><span class="token punctuation">:</span> yaml.org 
 <span class="token key atrule">Ruby</span><span class="token punctuation">:</span> ruby<span class="token punctuation">-</span>lang.org 
 <span class="token key atrule">Python</span><span class="token punctuation">:</span> python.org 
 <span class="token key atrule">Perl</span><span class="token punctuation">:</span> use.perl.org 
 
<span class="token comment"># 使用json表示</span>
<span class="token punctuation">{</span><span class="token key atrule">&quot;Websites&quot;</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>&quot;YAML&quot;<span class="token punctuation">:</span><span class="token string">&quot;yaml.org &quot;</span><span class="token punctuation">,</span> &quot;Ruby&quot;<span class="token punctuation">:</span><span class="token string">&quot;ruby-lang.org&quot;</span><span class="token punctuation">}</span><span class="token punctuation">}</span>

<span class="token comment"># 2</span>
<span class="token key atrule">languages</span><span class="token punctuation">:</span>
 <span class="token punctuation">-</span> Ruby
 <span class="token punctuation">-</span> Perl
 <span class="token punctuation">-</span> Python 
 <span class="token punctuation">-</span> c
 <span class="token comment"># 使用json表示</span>
 <span class="token punctuation">{</span>&quot;languages&quot;<span class="token punctuation">:</span><span class="token punctuation">[</span><span class="token string">&quot;ruby&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;perl&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;python&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;c&quot;</span><span class="token punctuation">]</span><span class="token punctuation">}</span>
 
<span class="token comment"># 3</span>
<span class="token punctuation">-</span>
  <span class="token punctuation">-</span> Ruby
  <span class="token punctuation">-</span> Perl
  <span class="token punctuation">-</span> Python 
<span class="token punctuation">-</span> 
  <span class="token punctuation">-</span> c
  <span class="token punctuation">-</span> c++
  <span class="token punctuation">-</span> java
 <span class="token comment"># 使用json表示</span>
<span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token string">&quot;ruby&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;perl&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;python&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">&quot;c&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;c++&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;java&quot;</span><span class="token punctuation">]</span><span class="token punctuation">]</span>
<span class="token comment"># 4</span>
<span class="token punctuation">-</span>
  <span class="token key atrule">id</span><span class="token punctuation">:</span> <span class="token number">1</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> huang
<span class="token punctuation">-</span>
  <span class="token key atrule">id</span><span class="token punctuation">:</span> <span class="token number">2</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> liao
<span class="token comment"># 使用json表示</span>
<span class="token punctuation">[</span><span class="token punctuation">{</span>&quot;id&quot;<span class="token punctuation">:</span><span class="token number">1</span><span class="token punctuation">,</span> &quot;name&quot;<span class="token punctuation">:</span><span class="token string">&quot;huang&quot;</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>&quot;id&quot;<span class="token punctuation">:</span><span class="token number">2</span><span class="token punctuation">,</span> &quot;name&quot;<span class="token punctuation">:</span><span class="token string">&quot;liao&quot;</span><span class="token punctuation">}</span><span class="token punctuation">]</span> 
</code></pre></div></li></ul> <p><strong>compose文件样例：</strong></p> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">'2'</span>                        <span class="token comment"># compose 版本号</span>
<span class="token key atrule">services</span><span class="token punctuation">:</span>                           <span class="token comment"># 服务标识符</span>
  <span class="token key atrule">web1</span><span class="token punctuation">:</span>                             <span class="token comment"># 子服务命名</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx                    <span class="token comment"># 服务依赖镜像属性</span>
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>                          <span class="token comment"># 服务端口属性</span>
      <span class="token punctuation">-</span> <span class="token string">&quot;9999:80&quot;</span>                   <span class="token comment"># 宿主机端口:容器端口</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>web1      <span class="token comment"># 容器命名</span>

</code></pre></div><p><strong>格式详解：</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code>compose版本号、服务标识符必须顶格写
属性名和属性值是以<span class="token string">': '</span><span class="token punctuation">(</span>冒号+空格<span class="token punctuation">)</span> 隔开
层级使用<span class="token string">'  '</span><span class="token punctuation">(</span>两个空格<span class="token punctuation">)</span>表示
服务属性使用<span class="token string">' - '</span><span class="token punctuation">(</span>空格空格-空格<span class="token punctuation">)</span>来表示
</code></pre></div><p><strong>compose属性介绍</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#镜像：</span>
    格式：
        image: 镜像名称:版本号
    举例：
        image: nginx:latest

<span class="token comment">#容器命名：</span>
    格式：
        container_name: 自定义容器命名
    举例：
        container_name: nginx-web1

<span class="token comment">#数据卷：</span>
    格式：
        volumes:
          - 宿主机文件:容器文件
    举例：
        volumes:
          - ./linshi.conf:/nihao/haha.sh

<span class="token comment">#端口：</span>
    格式：
        ports:
          - <span class="token string">&quot;宿主机端口:容器端口&quot;</span>
    举例：
        ports:
          - <span class="token string">&quot;9999:80&quot;</span>

<span class="token comment">#镜像构建：</span>
    格式：
        build: Dockerfile 的路径
    举例：
        build: <span class="token builtin class-name">.</span>
        build: ./dockerfile_dir/
        build: /root/dockerfile_dir/
<span class="token comment">#镜像依赖：</span>
    格式：
        depends_on:
          - 本镜像依赖于哪个服务
    举例：
        depends_on:
          - web1
<span class="token comment">#networks：</span>
加入指定网络，格式如下：
services:
  some-service:
    networks:
     - some-network
     - other-network
</code></pre></div><h3 id="_3-3-5-go项目实践"><a href="#_3-3-5-go项目实践" class="header-anchor">#</a> 3.3.5 go项目实践</h3> <p><strong>项目分析</strong></p> <p><img src="assets/1541773097819.png" alt="1541773097819"></p> <p><strong>需求：</strong></p> <p>自动部署一个集群，使用nginx代理两个go项目</p> <p><strong>流程分析：</strong></p> <p>1、go项目部署</p> <p>2、nginx代理部署</p> <p>3、docker 环境</p> <p>4、docker compose任务编排</p> <p><strong>技术点分析：</strong></p> <p>1、go项目部署</p> <p>go项目基础环境</p> <p>go项目配置</p> <p>2、nginx代理部署</p> <p>nginx的配置文件</p> <p>3、docker 环境</p> <p>docker基础镜像</p> <p>go镜像</p> <p>nginx镜像</p> <p>4、docker compose任务编排</p> <p>4个任务：1个镜像构建任务、2个go任务、1个nginx任务</p> <p>任务依赖关系：go任务执行依赖于nginx任务</p> <p>镜像依赖：go镜像依赖于nginx镜像完毕</p> <p><strong>实施方案：</strong></p> <p>1、基础环境</p> <p>1.1 compose基础目录</p> <p>1.2 环境依赖文件：</p> <p>sources.list、test.go、test1.go、test2.go、nginx-beego.conf</p> <p>1.3 dockerfile文件</p> <p>go项目环境的Dockerfile文件</p> <p>2、任务编排文件</p> <p>2.1 nginx任务</p> <p>基于nginx镜像，增加一个nginx的代理配置即可</p> <p>2.2 go基础镜像任务</p> <p>基于ubuntu镜像，构建go基础环境镜像，参考3.2.4内容</p> <p>该任务依赖于2.1 nginx任务</p> <p>2.3 go项目任务</p> <p>基于go基础镜像，增加测试文件即可</p> <p>该任务依赖于2.2 go基础镜像任务</p> <p>3、测试</p> <p>3.1 集群测试</p> <p>方案实施</p> <p>1、基础环境</p> <p>1.1 compose基础目录</p> <p>创建compose基础目录</p> <div class="language-shell extra-class"><pre class="language-shell"><code>:~$ <span class="token function">mkdir</span> /docker/compose/
:~$ <span class="token builtin class-name">cd</span> /docker/compose/
</code></pre></div><p>1.2 环境依赖文件：</p> <p><strong>nginx配置文件</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code>创建nginx专用目录
:~$ <span class="token function">mkdir</span> nginx
:~$ <span class="token builtin class-name">cd</span> nginx
创建nginx负载均衡配置nginx-beego.conf
:~$ <span class="token function">vim</span> nginx-beego.conf
</code></pre></div><p><strong>文件内容</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code>upstream beegos <span class="token punctuation">{</span>  
<span class="token comment">#upstream模块</span>
  server <span class="token number">192.168</span>.8.14:10086<span class="token punctuation">;</span>
  server <span class="token number">192.168</span>.8.14:10087<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
server <span class="token punctuation">{</span>
  listen <span class="token number">80</span><span class="token punctuation">;</span>
  <span class="token comment">#提供服务的端口 </span>
  server_name _<span class="token punctuation">;</span>
  <span class="token comment">#服务名称</span>
  location / <span class="token punctuation">{</span>
    proxy_pass http://beegos<span class="token punctuation">;</span>
    <span class="token comment">#反选代理 upstream模块  beegos</span>
    index index.html index.htm<span class="token punctuation">;</span>
    <span class="token comment">#默认首页</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>go<strong>基础镜像依赖文件</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#创建go基础镜像目录：</span>
:~$ <span class="token function">mkdir</span> go-base
:~$ <span class="token builtin class-name">cd</span> go-base
<span class="token comment">#创建source.lise</span>
:~$ <span class="token function">vim</span> sources.list
</code></pre></div><p><strong>文件内容</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code>deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe 
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse 
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiverse
</code></pre></div><p><strong>或者</strong></p> <div class="language-shell extra-class"><pre class="language-shell"><code>RUN <span class="token function">sed</span> -i <span class="token string">'s/archive.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list
RUN <span class="token function">sed</span> -i <span class="token string">'s/security.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list
</code></pre></div><p><strong>test.go配置文件</strong></p> <div class="language-Go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;github.com/astaxie/beego&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> MainController <span class="token keyword">struct</span> <span class="token punctuation">{</span> 
	beego<span class="token punctuation">.</span>Controller
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>this <span class="token operator">*</span>MainController<span class="token punctuation">)</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> 
	this<span class="token punctuation">.</span>Ctx<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span><span class="token string">&quot;hello world\n&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	beego<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>MainController<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
	beego<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>go任务依赖文件：
<strong>beego1/test.go配置文件</strong></p> <div class="language-go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token punctuation">(</span>
<span class="token string">&quot;github.com/astaxie/beego&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> MainController <span class="token keyword">struct</span> <span class="token punctuation">{</span> 
beego<span class="token punctuation">.</span>Controller
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>this <span class="token operator">*</span>MainController<span class="token punctuation">)</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> 
this<span class="token punctuation">.</span>Ctx<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span><span class="token string">&quot;&lt;h1&gt;hello beego1&lt;/h1&gt;\n&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
beego<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>MainController<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
beego<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p><strong>Beego2/test.go配置文件</strong></p> <div class="language-Go extra-class"><pre class="language-go"><code><span class="token keyword">package</span> main
<span class="token keyword">import</span> <span class="token punctuation">(</span>
	<span class="token string">&quot;github.com/astaxie/beego&quot;</span>
<span class="token punctuation">)</span>

<span class="token keyword">type</span> MainController <span class="token keyword">struct</span> <span class="token punctuation">{</span> 
	beego<span class="token punctuation">.</span>Controller
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>this <span class="token operator">*</span>MainController<span class="token punctuation">)</span> <span class="token function">Get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> 
	this<span class="token punctuation">.</span>Ctx<span class="token punctuation">.</span><span class="token function">WriteString</span><span class="token punctuation">(</span><span class="token string">&quot;&lt;h1&gt;hello beego2&lt;/h1&gt;\n&quot;</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	beego<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token string">&quot;/&quot;</span><span class="token punctuation">,</span> <span class="token operator">&amp;</span>MainController<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
	beego<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><p>1.3 dockerfile文件</p> <p>go项目环境的Dockerfile文件</p> <p>创建Dockerfile文件</p> <div class="language- extra-class"><pre class="language-text"><code>:~$ vim dockerfile
</code></pre></div><p>文件内容</p> <div class="language-Dockerfile extra-class"><pre class="language-dockerfile"><code><span class="token comment"># 构建一个基于ubuntu 的docker 定制镜像</span>
<span class="token comment"># 基础镜像</span>
<span class="token keyword">FROM</span> ubuntu
<span class="token comment"># 镜像作者</span>
<span class="token keyword">MAINTAINER</span> panda kstwoak47@163.com
<span class="token comment"># 增加国内源</span>
<span class="token comment">#COPY sources.list /etc/apt/</span>

<span class="token keyword">RUN</span> sed <span class="token punctuation">-</span>i <span class="token string">'s/archive.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list
<span class="token keyword">RUN</span> sed <span class="token punctuation">-</span>i <span class="token string">'s/security.ubuntu.com/mirrors.ustc.edu.cn/g'</span> /etc/apt/sources.list

<span class="token comment"># 执行命令</span>
<span class="token keyword">RUN</span> apt<span class="token punctuation">-</span>get update
<span class="token keyword">RUN</span> apt<span class="token punctuation">-</span>get install gcc libc6<span class="token punctuation">-</span>dev git lrzsz <span class="token punctuation">-</span>y
<span class="token comment">#将go复制解压到容器中</span>
<span class="token keyword">ADD</span> go1.10.linux<span class="token punctuation">-</span>amd64.tar.gz  /usr/local/
<span class="token comment"># 定制环境变量</span>
<span class="token keyword">ENV</span> GOROOT=/usr/local/go
<span class="token keyword">ENV</span> PATH=$PATH<span class="token punctuation">:</span>/usr/local/go/bin
<span class="token keyword">ENV</span> GOPATH=/root/go
<span class="token keyword">ENV</span> PATH=$GOPATH/bin/<span class="token punctuation">:</span>$PATH
<span class="token comment"># 下载项目</span>
<span class="token comment">#RUN go get github.com/astaxie/beego</span>
<span class="token keyword">ADD</span> astaxie.tar.xz  /root/go/src/github.com
<span class="token comment"># 增加文件</span>
<span class="token keyword">COPY</span> test.go /root/go/src/myTest/
<span class="token comment"># 定制工作目录</span>
<span class="token keyword">WORKDIR</span> /root/go/src/myTest/
<span class="token comment"># 对外端口</span>
<span class="token keyword">EXPOSE</span> 8080
<span class="token comment"># 运行项目</span>
<span class="token keyword">ENTRYPOINT</span> <span class="token punctuation">[</span><span class="token string">&quot;go&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;run&quot;</span><span class="token punctuation">,</span><span class="token string">&quot;test.go&quot;</span><span class="token punctuation">]</span>

</code></pre></div><p>最终的文件目录结构</p> <div class="language-shell extra-class"><pre class="language-shell"><code>:~<span class="token comment"># tree /docker/compose/</span>
/docker/compose/beego/
├── beego1
│   └── test.go
├── beego2
│   └── test.go
├── docker-compose.yml
├── go-base
│   ├── astaxie.tar.xz
│   ├── Dockerfile
│   ├── go1.10.linux-amd64.tar.gz
│   └── test.go
└── nginx
    └── nginx-beego.conf

</code></pre></div><p>2、任务编排文件</p> <p>docker-compose.yml文件内容</p> <div class="language-yml extra-class"><pre class="language-yml"><code><span class="token key atrule">version</span><span class="token punctuation">:</span> <span class="token string">'2'</span>
<span class="token key atrule">services</span><span class="token punctuation">:</span>
  <span class="token key atrule">web1</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> nginx
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">&quot;9999:80&quot;</span>
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> ./nginx/nginx<span class="token punctuation">-</span>beego.conf<span class="token punctuation">:</span>/etc/nginx/conf.d/default.conf
      <span class="token comment">#将配置文件映射到nginx的配置文件位置</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> nginx<span class="token punctuation">-</span>web1

  <span class="token key atrule">go-base</span><span class="token punctuation">:</span>
    <span class="token key atrule">build</span><span class="token punctuation">:</span> ./go<span class="token punctuation">-</span>base/
    <span class="token key atrule">image</span><span class="token punctuation">:</span> go<span class="token punctuation">-</span>base<span class="token punctuation">:</span>v0.1

  <span class="token key atrule">beego-web1</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> go<span class="token punctuation">-</span>base<span class="token punctuation">:</span>v0.1
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> ./beego1/test.go<span class="token punctuation">:</span>/root/go/src/myTest/test.go
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">&quot;10086:8080&quot;</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> beego<span class="token punctuation">-</span>web1
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> go<span class="token punctuation">-</span>base

  <span class="token key atrule">beego-web2</span><span class="token punctuation">:</span>
    <span class="token key atrule">image</span><span class="token punctuation">:</span> go<span class="token punctuation">-</span>base<span class="token punctuation">:</span>v0.1
    <span class="token key atrule">volumes</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> ./beego2/test.go<span class="token punctuation">:</span>/root/go/src/myTest/test.go
    <span class="token key atrule">ports</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> <span class="token string">&quot;10087:8080&quot;</span>
    <span class="token key atrule">container_name</span><span class="token punctuation">:</span> beego<span class="token punctuation">-</span>web2
    <span class="token key atrule">depends_on</span><span class="token punctuation">:</span>
      <span class="token punctuation">-</span> go<span class="token punctuation">-</span>base
</code></pre></div><p>3、 最后测试</p> <div class="language-shell extra-class"><pre class="language-shell"><code><span class="token comment">#构建镜像</span>
<span class="token variable">$docker</span>-compose build
<span class="token comment">#启动任务</span>
<span class="token variable">$docker</span>-compose up -d
<span class="token comment">#查看效果</span>
<span class="token variable">$docker</span>-compose <span class="token function">ps</span>
<span class="token comment">#浏览器访问</span>
<span class="token number">192.168</span>.110.5:9999
</code></pre></div></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">上次更新:</span> <span class="time">7/20/2020, 2:09:44 AM</span></div></footer> <!----> </main></div><div class="global-ui"></div></div>
    <script src="/assets/js/app.cb35c8f6.js" defer></script><script src="/assets/js/2.063846a6.js" defer></script><script src="/assets/js/4.1ffb4609.js" defer></script><script src="/assets/js/76.f54f3d4f.js" defer></script>
  </body>
</html>
